Как добавить отношение manytomany в другой класс. В моем случае в классе InfoCreateView

#python #django #django-views

#python #django #django-просмотры

Вопрос:

Я создаю страницу CV, я хочу связать свой класс (таблицу) навыков, языка и т. Д. С основной таблицей / классом Person, но для этого мне нужно сначала отправить таблицу навыков, потому что моя таблица person содержит внешний ключ для навыков. Но в соответствии с именем формы CV и личной информацией на первом месте. Кроме того, я могу поместить всю форму на одну страницу, но я хочу перейти на следующую страницу для каждой дополнительной информации, поэтому возможно ли передать данные запроса из одного представления на основе класса в другое представление на основе класса.

models.py

      from django.db import models
from django.core.validators import MinLengthValidator
from django.conf import settings
import datetime


class Workexperience(models.Model):
    work = models.CharField(null=True, blank=True,
                max_length=256,
                help_text='eg: Juniorengineer: at Lamp;T ')
    person = models.ForeignKey('Person', on_delete=models.CASCADE, blank=True, null=False, default=1 )
    def __str__(self):
        return self.work

class Education(models.Model):
    school = models.CharField(max_length=200)
    college = models.CharField(null=True, blank=True,max_length=200)
    person = models.ForeignKey('Person', on_delete=models.CASCADE, blank=True, null=False, default=1 )

    def __str__(self):
        return self.school

class Skills(models.Model):
    skill = models.CharField(
                max_length=256,
                help_text='Add skills sperated by commas eg: programming, Matlab')
    person = models.ForeignKey('Person', on_delete=models.CASCADE, blank=True, null=False, default=1 )

    def __str__(self):
        return self.skill


class Languages(models.Model):
    language = models.CharField(
                max_length=256,
                help_text='Add language sperated by commas eg: English, Gujarati')
    person = models.ForeignKey('Person', on_delete=models.CASCADE, blank=True, null=False, default=1 )

    def __str__(self):
        return self.language


class Person(models.Model):
    name = models.CharField(
            max_length=100,
            help_text='Enter a name (e.g. Harry Virani)',
            validators=[MinLengthValidator(2, "It must be greater than 1 character")]
    )
    picture = models.BinaryField(null=True, blank=True, editable=True)
    content_type = models.CharField(max_length=256, null=True, blank=True,
            help_text='The MIMEType of the file')

    profession = models.CharField(
            max_length=100,
            validators=[MinLengthValidator(2, "It must be greater than 1 character")]
    )
    owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, default='')

    address = models.CharField(max_length=256)
    email = models.EmailField(max_length = 254)
    phone = models.CharField(
            max_length=15,
            help_text='Enter a phone number like this (e.g.  91000000000)',
            validators=[MinLengthValidator(10, "It must be greater than 10 character")] )


    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    facebook = models.URLField(null=True, blank=True, max_length=200,
                help_text='enter your facebook URL'    )
    instagram = models.URLField(null=True, blank=True, max_length=200,
                help_text='enter your instagram link URL'  )
    linkedin = models.URLField(null=True, blank=True, max_length=200,
                help_text='enter your Linked link URL'     )

    skill =  models.ManyToManyField(Skills, related_name='skills',  default=1)
    language = models.ManyToManyField(Languages, related_name='languages', default=1)
    edu = models.ManyToManyField(Education,  default=1,related_name='edu' )
    work = models.ManyToManyField(Workexperience,default=1, blank=True, related_name='works')


    # Shows up in the admin list
    def __str__(self):
        return self.name
  

views.py

Я хочу сохранить его в другом классе, который предназначен для создания навыков и других моделей.

   class PersonCreateView(LoginRequiredMixin, View):
    template_name = 'MYP/form.html'
    success_url =  'MYP:myp_create_info'
    def get(self, request, pk=None):
        personform = PersonForm()
        ctx = { 'personform': personform}
        return render(request, self.template_name, ctx)
    def post(self, request, pk=None) :
        # if 'personform' in request.POST:
        personform = PersonForm(request.POST, request.FILES or None)

        if not personform.is_valid():
            ctx = {'personform': personform}
            return render(request, self.template_name, ctx)
        pform = personform.save(commit=False)
        #adding onwer
        pform.owner = self.request.user
        pform.save()
        return redirect(self.success_url, pform.id)

class InfoCreateView(LoginRequiredMixin, View):
    template_name = 'MYP/form2.html'
    success_url = reverse_lazy('MYP:all')
    def get(self, request, pk):
        person = get_object_or_404(Person,id=pk)
        skill= SkillsForm()
        skill_list = Skills.objects.filter(person=person)
        ctx = { 'skill':skill, 'skill_list':skill_list }
        return render(request, self.template_name, ctx)

    def post(self, request, pk):
        if 'skill' in request.POST:
            skill = SkillsForm(request.POST or None)
            if not skill.is_valid() :
                ctx = { 'skill':skill}
                return render(request, self.template_name, ctx)
            person = get_object_or_404(Person,id=pk)
            print(person)
            skill = Skills(skill=request.POST['skill'], person=person)
            skill.save()
            print(skill.person)
        return redirect('MYP:myp_create_info', pk=pk)
  

forms.py

     class PersonForm(forms.ModelForm):
    max_upload_limit = 2 * 1024 * 1024
    max_upload_limit_text = naturalsize(max_upload_limit)

    # Call this 'picture' so it gets copied from the form to the in-memory model
    # It will not be the "bytes", it will be the "InMemoryUploadedFile"
    # because we need to pull out things like content_type
    picture = forms.FileField(required=False, label='File to Upload <= ' max_upload_limit_text)
    upload_field_name = 'picture'

    # Hint: this will need to be changed for use in the ads application :)
    class Meta:
        model = Person
        fields = ['name', 'profession', 'picture', 'address', 'email', 'phone','facebook','linkedin','instagram']  # Picture is manual

    # Validate the size of the picture
    def clean(self) :
        cleaned_data = super().clean()
        pic = cleaned_data.get('picture')
        if pic is None : return
        if len(pic) > self.max_upload_limit:
            self.add_error('picture', "File must be < " self.max_upload_limit_text " bytes")

    # Convert uploaded File object to a picture
    def save(self, commit=True) :
        instance = super(PersonForm, self).save(commit=False)

        # We only need to adjust picture if it is a freshly uploaded file
        f = instance.picture   # Make a copy
        if isinstance(f, InMemoryUploadedFile):  # Extract data from the form to the model
            bytearr = f.read();
            instance.content_type = f.content_type
            instance.picture = bytearr  # Overwrite with the actual image data

        if commit:
            instance.save()

        return instance

class WorkexperienceForm(forms.ModelForm):
     class Meta:
        model = Workexperience
        fields = ['work']


class EducationForm(forms.ModelForm):
     class Meta:
        model = Education
        fields = ['school','college']

class SkillsForm(forms.ModelForm):
     class Meta:
        model = Skills
        fields = ['skill']

class LanguagesForm(forms.ModelForm):
     class Meta:
        model = Languages
        fields = ['language']
      
  

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

Комментарии:

1. Я не понимаю, почему вы не добавляете свой ForeignKey to Person в Skill ? Тогда у человека может быть 0, 1 или более навыков, связанных с ним, и это позволит вам использовать встроенные наборы форм ( docs.djangoproject.com/en/3.1/topics/forms/modelforms /… )

2. Я отредактировал свою модель и представления, также я прочитал наборы форм ilnine, также я хочу добавить несколько навыков одним человеком, можете ли вы что-нибудь предложить?

3. То есть вы имеете в виду, что один навык может использоваться несколькими пользователями, а один пользователь может иметь несколько навыков? Если это правда, вы должны сохранить только ManyToManyField в своей Person модели и удалить ForeignKeys добавленные навыки, опыт работы, образование, язык. Тогда я предлагаю вам создать первую форму для создания вашего персонажа, а другую — для добавления навыков, опыта работы, образования, языков. Пользователь может создать новый или выбрать существующие.

4. проверьте мой views.py Могу ли я отделить его с помощью этой функции от того, что я должен сделать что-то еще. ? Я удалил внешние ключи person из моделей.

5. Да, это можно сделать так, как вы делали в своих представлениях, но я считаю, что имеет смысл иметь один Skill экземпляр для одного навыка, поскольку несколько человек могут обладать одним и тем же навыком. Это нормализация базы данных.( en.wikipedia.org/wiki/Database_normalization ). Поэтому я думаю, что вам следует переименовать skill по name (навыку) в вашей Skill модели.

Ответ №1:

На мой взгляд, ваши модели перепутаны. Вот как я бы их написал :

 class WorkExperience(models.Model):
    work = models.CharField(
        blank=True,
        max_length=256,
        help_text='eg: Juniorengineer: at Lamp;T'
    )

    def __str__(self):
        return self.work


class Education(models.Model):
    school = models.CharField(max_length=200)
    college = models.CharField(blank=True, max_length=200)

    def __str__(self):
        return self.school


class Skill(models.Model):
    name = models.CharField(
        max_length=256,
        help_text='Add a skill name (eg: Programming)'
    )

    def __str__(self):
        return self.name


class Language(models.Model):
    name = models.CharField(
        max_length=256,
        help_text='Add a language name (eg: Gujarati)'
    )

    def __str__(self):
        return self.name


class Person(models.Model):
    name = models.CharField(
        max_length=100,
        help_text='Enter a name (e.g. Harry Virani)',
        validators=[MinLengthValidator(2, "It must be greater than 1 character")]
    )
    
    # [...Other fields...]
    
    skills =  models.ManyToManyField(Skill, related_name='persons', blank=True)
    languages = models.ManyToManyField(Language, related_name='persons', blank=True)
    educations = models.ManyToManyField(Education, related_name='persons', blank=True)
    work_experiences = models.ManyToManyField(WorkExperience, related_name='persons', blank=True)

    def __str__(self):
        return self.name
  

Тогда мне нужно увидеть ваш forms.py , чтобы лучше понять, как вы справляетесь с этим в своем представлении.

Комментарии:

1. Я добавляю внешние ключи person, потому что это позволит мне вызывать определенный навык через person.