Django FileField run_time पर निर्धारित रनटाइम के साथ


130

मैं अपने अपलोड सेट करने का प्रयास कर रहा हूं ताकि यदि उपयोगकर्ता जो फ़ाइल को अपलोड करता है तो वह MEDIA_ROOT / joe के रूप में चला जाता है क्योंकि सभी की फ़ाइलें MEDIA_ROOT पर जाने के लिए विरोध करती हैं। समस्या यह है कि मुझे नहीं पता कि इसे मॉडल में कैसे परिभाषित किया जाए। यहाँ यह वर्तमान में कैसा दिखता है:

class Content(models.Model):
    name = models.CharField(max_length=200)
    user = models.ForeignKey(User)
    file = models.FileField(upload_to='.')

इसलिए मैं जो चाहता हूं, उसकी जगह 'है।' अपलोड_ के रूप में, क्या यह उपयोगकर्ता का नाम है।

मैं समझता हूं कि Django 1.0 के रूप में आप upload_to को संभालने के लिए अपने स्वयं के फ़ंक्शन को परिभाषित कर सकते हैं, लेकिन उस फ़ंक्शन को यह पता नहीं है कि उपयोगकर्ता कौन होगा या तो मैं थोड़ा खो गया हूं।

सहायता के लिए धन्यवाद!

जवाबों:


256

आपने शायद दस्तावेज़ीकरण पढ़ लिया है , इसलिए इसे समझने के लिए यहां एक आसान उदाहरण है:

def content_file_name(instance, filename):
    return '/'.join(['content', instance.user.username, filename])

class Content(models.Model):
    name = models.CharField(max_length=200)
    user = models.ForeignKey(User)
    file = models.FileField(upload_to=content_file_name)

जैसा कि आप देख सकते हैं, आपको दिए गए फ़ाइलनाम का उपयोग करने की भी आवश्यकता नहीं है - यदि आप इसे पसंद करते हैं, तो आप इसे अपने अपलोड_ में भी ओवरराइड कर सकते हैं।


हाँ, यह संभवतः डॉक्स में है - यह IRC पर एक बहुत ही सामान्य प्रश्न है
स्माइलीक्रिस

2
क्या यह ModelForm के साथ काम करता है? मैं देख सकता हूं कि उदाहरण में वर्ग मॉडल की सभी विशेषताएं हैं, लेकिन कोई मूल्य नहीं हैं (केवल फ़ील्ड नाम के एक तार)। टेम्पलेट में, उपयोगकर्ता छिपा हुआ है। मुझे एक प्रश्न प्रस्तुत करना पड़ सकता है, मैं इसे घंटों तक टालता रहा हूं।
mgag

3
अजीब तरह से यह मूल रूप से एक ही सेटअप में मुझ पर विफल हो रहा है। inst.user की कोई विशेषता नहीं है।
बॉब स्प्रीएन

11
आप यह सुनिश्चित करने के os.path.joinबजाय '/'.joinकि यह यूनिक्स सिस्टम पर भी काम करता है, का उपयोग करना चाहते हैं । वे दुर्लभ हो सकते हैं, लेकिन यह अच्छा अभ्यास है;)
Xudonax

2
नमस्ते, मैंने एक ही कोड की कोशिश की, उन्हें मॉडल-थ्रेड में रखा, लेकिन त्रुटि प्राप्त करें सामग्री ऑब्जेक्ट में कोई विशेषता नहीं है 'उपयोगकर्ता'।
हैरी

12

इससे वाकई मदद मिली। थोड़े अधिक संक्षिप्तता के लिए, मेरे मामले में लंबोदर का उपयोग करने का फैसला किया:

file = models.FileField(
    upload_to=lambda instance, filename: '/'.join(['mymodel', str(instance.pk), filename]),
)

4
यह मेरे लिए Django 1.7 में माइग्रेशन का उपयोग करके काम नहीं किया। इसके बजाय एक फंक्शन तैयार किया और माइग्रेशन लिया।
बारेरन

यहां तक ​​कि अगर आप str (उदाहरण। Pk) का उपयोग करके काम करने के लिए लैम्ब्डा प्राप्त नहीं कर सकते हैं, तो एक अच्छा विचार है अगर आपको फ़ाइलों को ओवरराइट करने की समस्या है जब आप उन्हें नहीं चाहते हैं।
जोसेफ दतिलो

2
उदाहरण के पास pkबचत करने से पहले नहीं है । यह केवल अपडेट नहीं कृतियों (आवेषण) के लिए काम करता है।
मोहम्मद जाफ़र मशहदी

लैम्ब्डा migrationsसंचालन में काम नहीं करता है क्योंकि यह डॉक्स के
अब्राहिम करीमी

4

'उदाहरण' ऑब्जेक्ट के pk मान का उपयोग करने पर एक नोट। प्रलेखन के अनुसार:

ज्यादातर मामलों में, इस ऑब्जेक्ट को अभी तक डेटाबेस में सहेजा नहीं गया है, इसलिए यदि यह डिफ़ॉल्ट ऑटोफ़िल्ड का उपयोग करता है, तो इसके प्राथमिक कुंजी फ़ील्ड के लिए इसका मान अभी तक नहीं हो सकता है।

इसलिए पीके का उपयोग करने की वैधता इस बात पर निर्भर करती है कि आपका विशेष मॉडल कैसे परिभाषित किया गया है।


मुझे मूल्य के रूप में कोई नहीं मिल रहा है। मैं यह पता नहीं लगा सकता कि इसे कैसे ठीक किया जाए। क्या आप थोड़ा विस्तार से बता सकते हैं।
अमन दीप

1

यदि आपको माइग्रेशन की समस्या है तो आपको संभवतः @deconstructibleडेकोरेटर का उपयोग करना चाहिए ।

import datetime
import os
import unicodedata

from django.core.files.storage import default_storage
from django.utils.deconstruct import deconstructible
from django.utils.encoding import force_text, force_str


@deconstructible
class UploadToPath(object):
    def __init__(self, upload_to):
        self.upload_to = upload_to

    def __call__(self, instance, filename):
        return self.generate_filename(filename)

    def get_directory_name(self):
        return os.path.normpath(force_text(datetime.datetime.now().strftime(force_str(self.upload_to))))

    def get_filename(self, filename):
        filename = default_storage.get_valid_name(os.path.basename(filename))
        filename = force_text(filename)
        filename = unicodedata.normalize('NFKD', filename).encode('ascii', 'ignore').decode('ascii')
        return os.path.normpath(filename)

    def generate_filename(self, filename):
        return os.path.join(self.get_directory_name(), self.get_filename(filename))

उपयोग:

class MyModel(models.Model):
    file = models.FileField(upload_to=UploadToPath('files/%Y/%m/%d'), max_length=255)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.