বিদ্যমান ফাইলটিতে জ্যাঙ্গোর ফাইলফিল্ড সেট করুন Set


90

আমার ডিস্কে একটি বিদ্যমান ফাইল আছে (বলুন / ফোল্ডার / ফাইল / টেক্সট) এবং জাজানোতে একটি ফাইলফিল্ড মডেল ক্ষেত্র।

যখন আমি করি

instance.field = File(file('/folder/file.txt'))
instance.save()

এটি ফাইলটিকে পুনরায় সংরক্ষণ করে file_1.txt(পরের বারের মতো এটি _2ইত্যাদি)।

আমি বুঝতে পারি কেন তবে আমি এই আচরণটি চাই না - আমি জানি যে ফিল্ডটি আমি যুক্ত করতে চাই সেগুলি অবশ্যই আমার জন্য অপেক্ষা করছে এবং আমি চাই জাঙ্গো এটির দিকে লক্ষ্য করুক।

কীভাবে?


4
জ্যাঙ্গো বা সাবক্ল্যাসিং সংশোধন না করে আপনি যা চান তা পেতে পারেন তা নিশ্চিত নন FileField। যখনই একটি FileFieldসংরক্ষণ করা হয় তখনই ফাইলটির একটি নতুন অনুলিপি তৈরি হয়। এটি এড়াতে কোনও বিকল্প যুক্ত করা মোটামুটি সোজা হবে।
মাইকেল মায়ার

হ্যাঁ, দেখে মনে হচ্ছে আমাকে সাবক্লাস করতে হবে এবং একটি পরম যুক্ত করতে হবে। আমি এই সাধারণ কাজের জন্য অতিরিক্ত টেবিল তৈরি করতে চাই না
গার্ড

4
ফাইলটিকে অন্য কোনও স্থানে রাখুন, এই পথ দিয়ে আপনার ক্ষেত্র তৈরি করুন, এটি সংরক্ষণ করুন এবং তারপরে আপনি ফাইলটি আপলোড_তে গন্তব্যস্থলে রাখবেন।
বেঞ্জোমিং

উত্তর:


22

আপনি যদি স্থায়ীভাবে এটি করতে চান তবে আপনার নিজের ফাইলস্টোরাজ বর্গ তৈরি করতে হবে

import os
from django.conf import settings
from django.core.files.storage import FileSystemStorage

class MyFileStorage(FileSystemStorage):

    # This method is actually defined in Storage
    def get_available_name(self, name):
        if self.exists(name):
            os.remove(os.path.join(settings.MEDIA_ROOT, name))
        return name # simply returns the name passed

এখন আপনার মডেলটিতে, আপনি আপনার পরিবর্তিত মাইফিল স্টোরেজ ব্যবহার করুন

from mystuff.customs import MyFileStorage

mfs = MyFileStorage()

class SomeModel(model.Model):
   my_file = model.FileField(storage=mfs)

ওহ, আশাব্যঞ্জক দেখাচ্ছে ফাইলফিল্ডের কোডটি কুয়াস হ'ল দারুণ জ্ঞানহীন
গার্ড

তবে ... প্রতি অনুরোধের ভিত্তিতে স্টোরেজ পরিবর্তন করা কি সম্ভব: যেমন: ফিল্ডস্টেস.স্টোরেজ = এমএফএস; উদাহরণ.ফিল্ড.সেভ (নাম, ফাইল); তবে আমার কোডের ভিন্ন শাখায় এটি করছেন না
গার্ড

4
না, যেহেতু স্টোরেজ ইঞ্জিনটি মডেলের সাথে আবদ্ধ। আপনি কেবল নিজের ফাইলের পাথকে একটি FilePathFieldবা সরল পাঠ্য হিসাবে স্টোর করে এড়াতে পারবেন can
বুরহান খালিদ

আপনি কেবল একটি নাম ফেরত দিতে পারবেন না। আপনাকে প্রথমে বিদ্যমান ফাইলটি সরিয়ে ফেলতে হবে।
আলেকজান্ডার শিপিন্ডার

124

সবেমাত্র instance.field.nameআপনার ফাইলের পথে সেট করুন

যেমন

class Document(models.Model):
    file = FileField(upload_to=get_document_path)
    description = CharField(max_length=100)


doc = Document()
doc.file.name = 'path/to/file'  # must be relative to MEDIA_ROOT
doc.file
<FieldFile: path/to/file>

15
আপনার থেকে আপেক্ষিক পথ MEDIA_ROOT, এটি।
mgalgs

7
এই উদাহরণে, আমি মনে করি আপনি কেবল করতে পারেনdoc.file = 'path/to/file'
এন্ড্রু সুইহার্ট

14

এটি চেষ্টা করুন ( ডক ):

instance.field.name = <PATH RELATIVE TO MEDIA_ROOT> 
instance.save()

5

নিজের স্টোরেজ ক্লাসটি লেখাই ঠিক। তবে get_available_nameডান পদ্ধতি ওভাররাইড করতে নয়।

get_available_nameযখন জাঙ্গো একই নামের একটি ফাইল দেখে এবং নতুন উপলব্ধ ফাইলের নাম পাওয়ার চেষ্টা করে তখন তাকে ডাকা হয়। এটি সেই নাম নয় যা নামটির পুনরায় নামকরণ করে। পদ্ধতি যে কারণে _save। মন্তব্যগুলি _saveবেশ ভাল এবং আপনি সহজেই এটি পতাকা সহ লেখার জন্য ফাইলটি খুলতে পারবেন os.O_EXCLযা একই ফাইলের নাম ইতিমধ্যে উপস্থিত থাকলে একটি OSError নিক্ষেপ করবে। জ্যাঙ্গো তখন এই ত্রুটিটি কল করেget_available_name একটি নতুন নাম পাওয়ার জন্য করে।

সুতরাং আমি মনে করি সঠিক উপায় হ'ল ওভাররাইড করা _saveএবং পতাকা ছাড়াই os.open () কল করা os.O_EXCL। পরিবর্তনটি বেশ সহজ তবে পদ্ধতিটি একটু দীর্ঘ হ'ল আমি এখানে এটি আটকালাম না। আপনার আরও সাহায্যের প্রয়োজন হলে আমাকে বলুন :)


এটি কোডের 50 টি লাইন যা আপনাকে অনুলিপি করতে হবে, এটি বেশ খারাপ। Get_av উপলভ্য_নামাকে ওভাররাইড করা আরও বিচ্ছিন্ন, খাটো এবং আরও নিরাপদ বলে মনে হচ্ছে ভবিষ্যতে জ্যাঙ্গোর নতুন সংস্করণগুলিতে আপগ্রেড করা
মাইকেল জেন্ডিন ২৯:১২

4
কেবলমাত্র ওভাররাইডিংয়ের সমস্যাটি get_available_nameহ'ল আপনি যখন একই নামে কোনও ফাইল আপলোড করবেন তখন সার্ভারটি একটি অন্তহীন লুপে প্রবেশ করবে। যেহেতু _saveফাইলটির নাম যাচাই করে এবং একটি নতুন পাওয়ার সিদ্ধান্ত নেয় তবে get_available_nameএখনও সেই সদৃশটি ফেরত দেয়। সুতরাং আপনার উভয়কে ওভাররাইড করা দরকার।
x1a0

4
ওফস, আমরা দুটি প্রশ্নে এই আলোচনা করছি, তবে কেবল এখনই আমি লক্ষ্য করেছি যে সেগুলি কিছুটা আলাদা) সুতরাং আমি এই প্রশ্নে ঠিক আছি, এবং আপনি এতে
মাইকেল জেন্ডিন

1

আমার সত্যিকার অর্থে একই সমস্যা ছিল! তখন আমি বুঝতে পারি যে আমার মডেলগুলি এটির কারণ হয়েছিল। উদাহরণস্বরূপ আমি এইভাবে আমার মডেলগুলি হড করি:

class Tile(models.Model):
  image = models.ImageField()

তারপরে, আমি আরও একটি টাইল একই ডিস্কে একই ফাইলটি উল্লেখ করতে চাই! আমি যেভাবে এটি সমাধান করতে পেলাম তা হ'ল আমার মডেল কাঠামোটিকে এটিতে পরিবর্তন করুন:

class Tile(models.Model):
  image = models.ForeignKey(TileImage)

class TileImage(models.Model):
  image = models.ImageField()

কোনটি আমি বুঝতে পারার পরে আরও বুদ্ধিমান হলাম, কারণ যদি আমি একই ফাইলটি আরও বেশি করে সংরক্ষণ করা চাই তবে আমার ডিবিতে একটির জন্য আমাকে অন্য একটি টেবিল তৈরি করতে হবে!

আমার ধারণা আপনিও এরকম সমস্যার সমাধান করতে পারবেন, আশা করি আপনি মডেলগুলি পরিবর্তন করতে পারবেন!

সম্পাদনা

এছাড়াও আমি অনুমান করি আপনি উদাহরণস্বরূপ এর মতো একটি পৃথক সঞ্চয়স্থান ব্যবহার করতে পারেন: SyMLinkOrCopyStorage

http://code.welldev.org/django-storages/src/11bef0c2a410/storages/backends/symlinkorcopy.py


আপনার ক্ষেত্রে বোঝায়, আমার নয়। আমি চাই না যে এটি একাধিকবার উল্লেখ করা হোক। আমি কোনও ফাইলকে রেফারেন্স করে একটি অবজেক্ট তৈরি করি, তখন আমি বুঝতে পারি যে অন্যান্য অ্যাটর্সগুলিতে ত্রুটি রয়েছে, এবং আমি তৈরির ফর্মটি আবার খুলি। পুনরায় জমা দেওয়ার সময় আমি যে ফাইলটি ইতিমধ্যে ডিস্কে সংরক্ষিত আছে সেটিকে আলগা করতে চাই না
গার্ড

সুতরাং আমার ধারণা আপনি আমার পদ্ধতির ব্যবহার করতে পারেন! কারণ আপনার কাছে একটি টেবিল ফর্মফাইল থাকবে যা কেবল তখনই আপনার কাছে ফাইলটি ধরে রাখবে! তারপরে আপনার ফর্ম টেবিলটিতে আপনার কাছে সেই ফাইলটির জন্য এফকে থাকবে! সুতরাং আপনি একই ফাইলের জন্য নতুন ফর্মগুলি পরিবর্তন / তৈরি করতে পারেন! (বিটিডব্লিউ আমি আমার মূল উদাহরণে এফকে এর ক্রম পরিবর্তন করছি)
আর্থার নেভেস

আপনি যদি নিজের পোস্টে আপনার ডোমেন (মডেল) পোস্ট করতে চান! আমি একটি ভাল ধারণা থাকতে পারে!
আর্থার Neves

ডোমেনটি আসলে কিছু যায় আসে না - এর সাথে যুক্ত একটি ফটো সহ আমার একটি মডেল রয়েছে এবং আমার কাস্টম এডিটিং স্ক্রিন রয়েছে। একবার আপলোড করা হয়েছে আমি চাইছি যে ছবিটি সার্ভারে থাকুক, তবে আমি আসলে একটি আলাদা মডেল, টেবিল এবং এফকে লুকোচুরি তৈরি করতে পছন্দ করি না কারণ কেবল এটি কাঠামোর সীমাবদ্ধতা বলে মনে হয়
গার্ড

এখানে আমি সীমাবদ্ধতাটি অনুমান করি কারণ আপনি যখন জ্যাঙ্গোতে কোনও ফাইলফিল্ড সংরক্ষণ করেন, সর্বদা এটি জ্যাঙ্গো স্টোরেজগুলির মধ্য দিয়ে যায়! সুতরাং এটি বোঝায় না যে আপনি কেবল একটি ফাইলের পথকে জোর করে! এছাড়াও জাঙ্গো কীভাবে জানবে যে ফাইলটি ইতিমধ্যে পথে রয়েছে? আপনি ব্যবহার করতে পারেন এমন অন্য পদ্ধতির পরিবর্তে ফাইলপ্যাথফিল্ড ব্যবহার করা হচ্ছে! যাতে আপনি কেবল আপনার ডিবিতে পথ নির্ধারণ করতে পারেন এবং অনুসন্ধানটিকে আপনার নিজের মতো করে সেরা মনে করতে পারেন!
আর্থার নেভেস

1

আপনার নিজের স্টোরেজটি সংজ্ঞায়িত করা উচিত, ফাইলসিস্টেমস্টোরেজ থেকে উত্তরাধিকারী হওয়া এবং OS_OPEN_FLAGSশ্রেণীর বৈশিষ্ট্য এবং get_available_name()পদ্ধতি ওভাররাইড করা উচিত :

জ্যাঙ্গো সংস্করণ: ৩.১

প্রকল্প / কোর / ফাইল / স্টোরেজ / ব্যাকেন্ডস / স্থানীয়.পি

import os

from django.core.files.storage import FileSystemStorage


class OverwriteStorage(FileSystemStorage):
    """
    FileSystemStorage subclass that allows overwrite the already existing
    files.
    
    Be careful using this class, as user-uploaded files will overwrite
    already existing files.
    """

    # The combination that don't makes os.open() raise OSError if the
    # file already exists before it's opened.
    OS_OPEN_FLAGS = os.O_WRONLY | os.O_TRUNC | os.O_CREAT | getattr(os, 'O_BINARY', 0)

    def get_available_name(self, name, max_length=None):
        """
        This method will be called before starting the save process.
        """
        return name

আপনার মডেলটিতে আপনার কাস্টম ওভাররাইট স্টোরেজটি ব্যবহার করুন

myapp / Model.py

from django.db import models

from core.files.storages.backends.local import OverwriteStorage


class MyModel(models.Model):
   my_file = models.FileField(storage=OverwriteStorage())
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.