Django m2m как использовать имя вместо name_id - PullRequest
0 голосов
/ 25 марта 2019

Я хочу добавить теги для новых сообщений. Я использую ввод тегов начальной загрузки. Это работает, только если я пишу tags_id, а не заголовок тега. И если я пишу новые номера, он сохраняет запись с новым тегом номера.

Как изменить tag_id на tag_title в таблице базы данных m2m или другим способом это исправить?

модель

class Tag(models.Model):
    title = models.CharField(max_length=50)
    slug = models.SlugField(max_length=50, unique=True)

class Post(models.Model):
    title = models.CharField(max_length=150, db_index=True)
    slug = models.SlugField(max_length=150, blank=True, unique=True)
    body = RichTextField()
    date_pub = models.DateTimeField(auto_now_add=True)
    tags = models.ManyToManyField(Tag, blank=True, related_name='posts')
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    views = models.IntegerField(blank=True, default=0)

вид

def post(self, request):
    tags = request.POST.getlist('tags')
    for tag in tags:
        objs, created = Tag.objects.get_or_create(title=tag, slug=tag)
    bound_form = self.model_form(request.POST))
    if bound_form.is_valid():
        post = bound_form.save(commit=False)
        post.author = request.user
        post.save()
        post.tags.add(objs)
        post.save()

        new_obj = bound_form.save()
        return redirect(new_obj)
    return render(request, self.template, context={'form': bound_form})

форма

class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ['title', 'slug', 'body', 'tags']
        widgets = {
            'title': forms.TextInput(attrs={'class': 'form-control'}),
            'slug': forms.TextInput(attrs={'class': 'form-control'}),
            'body': forms.Textarea(attrs={'class': 'form-control'}),
            'tags': forms.SelectMultiple(attrs={'class': 'form-control', 'data-role': 'tagsinput'}),

        }
        exclude = ['author',]

Я хочу, чтобы теги были словами, а не идентификаторами. Теперь, когда я добавляю слова, отображается ошибка: «qwe» не является допустимым значением. Он хочет цифры и, возможно, исправить отображение всех тегов в select. введите описание изображения здесь

1 Ответ

1 голос
/ 26 марта 2019

Как определена ваша модель, вы не можете использовать title в качестве уникального идентификатора для вашего тега. Также, если вы позволяете людям создавать новые теги, вы, возможно, захотите принять во внимание, что «виндсерфинг», «виндсерфинг» и «виндсерфинг» - это одно и то же.

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

Итак, ваша HTML-форма должна опубликовать список строк в форме Django. И в вашей форме вам нужно обработать эти строки для сохранения в виде тегов:

  • В вашем PostForm добавьте поле tags как поле TextInput. Это тот, который вы будете отображать как вводные теги в HTML-форме.
  • Удалить 'tags' из списка fields в ModelForm.
  • Переопределите метод __init__() для PostForm, чтобы установить начальные значения tags в качестве списка названий через запятую: self.fields['tags'].initial = ",".join([tag.title for tag in self.instance.tags.all()])
  • Переопределите метод clean_tags(), чтобы убедиться, что ввод представляет собой список строк, разделенных запятыми, возможно, изменив их все на строчные.
  • Переопределить метод save() для обработки тегов:
def save(commit=True):
    post = super().save(commit=commit)
    if commit:  # only save new tags if commit == True
        tags_titles = self.cleaned_data['tags'].split(",")
        for title in tags_titles:
            tag = Tag.objects.get_or_create(title=title.lower())  # assuming slug is auto-created when saving and all titles are saved lowercase
            post.tags.add(tag)
    return post

Так что в основном ваши формы просто обрабатывают строку (список строк через запятую), которые являются названиями ваших тегов. И ваша форма Django переводит это обратно в фактические Tag объекты.

...