Джанго: Загрузить файл и прочитать его содержимое, чтобы заполнить модель? - PullRequest
8 голосов
/ 23 мая 2011

Я новичок в Django и хотел бы знать, что такое Django-способ добавлять элементы в базу данных не путем ввода каждого поля из HTML-формы (как это делается по умолчанию), а с загрузкой одного файла (например,файл json), который будет использоваться для заполнения базы данных?

Итак, скажем, модель имеет только три поля: название, описание, количество.И у меня есть текстовый файл (myFile.txt) с надписью «myTitle: myDesc».

Мне нужен только FileField, который будет принимать текстовый файл, чтобы я мог загрузить myFile.txt и заголовоки описание будет прочитано из этого файла.И в то же время количество будет запрашиваться «обычно» в текстовом вводе, как это было бы по умолчанию (из файла считываются только заголовок и описание).

Конечно, проверка файла будетсделано, чтобы принять / отклонить загруженный файл.Проблема, с которой я сталкиваюсь, заключается в том, что если я добавлю FileField в модель, файл будет сохранен в локальном хранилище.Я хочу, чтобы содержимое загруженного файла было прочитано, использовано для создания записи в модели, а затем удалено.

Даже администратор не должен иметь возможность вручную добавлять элемент, вводя заголовок и описание вHTML-форма, но только путем загрузки файла.Может ли кто-нибудь помочь мне в Django-way?

Ответы [ 4 ]

8 голосов
/ 23 мая 2011

Вы можете создать две формы:

  1. Форма на основе django.forms.Form, которая используется для получения файла из запроса
  2. Форма модели, которая используется для проверки полей модели и создания объекта модели

Затем вы можете вызвать вторую форму из первой, например:

class MyModelForm(ModelForm):

    class Meta:
        model = MyModel


class FileUploadForm(forms.Form):

    file = forms.FileField()

    def clean_file(self):
        data = self.cleaned_data["file"]
        # read and parse the file, create a Python dictionary `data_dict` from it
        form = MyModelForm(data_dict)
        if form.is_valid():
            # we don't want to put the object to the database on this step
            self.instance = form.save(commit=False) 
        else:
            # You can use more specific error message here
            raise forms.ValidationError(u"The file contains invalid data.")
        return data

    def save(self):
        # We are not overriding the `save` method here because `form.Form` does not have it. 
        # We just add it for convenience.
        instance = getattr(self, "instance", None)
        if instance:
            instance.save()
        return instance

def my_view(request):
    form = FileUploadForm(request.POST, request.FILES)
    if form.is_valid():
        form.save()
    else:
        # display errors
2 голосов
/ 23 мая 2011

Вы можете использовать мастер форм для выполнения таких задач.Основная идея заключается в создании двух форм;одна с FileField и другая форма с заголовком, полями количества описания.

Пользователь просматривает форму сначала с FileField.Как только пользователь загрузит файл и отправит запрос, вы можете отобразить другую форму с начальными значениями, считанными из файла (вы также можете удалить файл на этом шаге).

Что касается функциональности администратора, вы можете прочитать о том, как интегрировать мастер форм с администратором здесь

1 голос
/ 04 октября 2011

Я нашел другой способ заполнения модели перед ее сохранением.

Вместо использования pre_save или использования двух разных форм, если мы используем admin.ModelAdmin, мы можем просто переопределить метод save_model ():

def save_model(self, request, obj, form, change):
  obj.user = request.user
  # populate the model
  obj.save()
  # post actions if needed
0 голосов
/ 23 мая 2011

Для этого вам нужно написать собственный код.Каждый FileField имеет подключенный объект File .Вы можете читать содержимое этого файлового объекта так же, как и при работе с файлами в Python.

Конечно, есть разные места, где вы можете это сделать.Вы можете перезаписать метод сохранения форм / моделей, который содержит FileField.Если у вас есть модель, вы также можете использовать сигналы pre_save / post_save.

...