Rafi Ki
Rafi Ki

Reputation: 131

Add an exception for model relationship of a specific object

I am kind a newbie in django and python. In my app each user is assigned many projects but each project has a specific user. What I am trying to achieve is to show to a user that never created any project, a project demo.

I tried that when a user register he is directly assigned the demo project but since a project can have only one user is does not work when another sign in..

Is it possible to create an exception to a model attribute et to specify that for a specific Project can have multiple users ?

Here is my code: Project model :

class Project(models.Model):

    name = models.CharField(max_length=250)
    team_id = models.ForeignKey(Team, blank=True, null=True)
    project_hr_admin = models.ForeignKey('registration.MyUser', blank=True, null=True)
    candidat_answers = models.ManyToManyField('survey.response')
    applicant = models.ManyToManyField(MyUser, related_name="applicant")
    created_at = models.DateTimeField(auto_now_add=True)

    def get_absolute_url(self):
        return reverse('website:ProjectDetails', kwargs={'pk1': self.pk})

Register a user :

def registerManager(request):
    #import pdb; pdb.set_trace()
    registered = False
    if request.method == "POST":
        Manager_form = ManagerForm(data=request.POST)

        if Manager_form.is_valid():
            user = Manager_form.save()
            user.set_password(user.password)
            user.is_manager = True
            user.save()
            registered = True
            login(request, user)
            demoProject = Project.objects.get(name="Project SoftScores")
            request.user.project_set.add(demoProject)
            return HttpResponseRedirect(reverse('website:hr_index'))
        else:
            print("Error!")
    else:
        Manager_form = ManagerForm()
    return render(request, 'HR_registration_form.html',
                  {'Manager_form': Manager_form,
                   'registered': registered})

Error message: SystemCheckError: System check identified some issues:

ERRORS:

website.DemoProject.applicant: (fields.E304) Reverse accessor for 'DemoProject.applicant' clashes with reverse ac
cessor for 'Project.applicant'.
        HINT: Add or change a related_name argument to the definition for 'DemoProject.applicant' or 'Project.app
licant'.
website.DemoProject.applicant: (fields.E305) Reverse query name for 'DemoProject.applicant' clashes with reverse
query name for 'Project.applicant'.
        HINT: Add or change a related_name argument to the definition for 'DemoProject.applicant' or 'Project.app
licant'.
website.Project.applicant: (fields.E304) Reverse accessor for 'Project.applicant' clashes with reverse accessor f
or 'DemoProject.applicant'.
        HINT: Add or change a related_name argument to the definition for 'Project.applicant' or 'DemoProject.app
licant'.
website.Project.applicant: (fields.E305) Reverse query name for 'Project.applicant' clashes with reverse query na
me for 'DemoProject.applicant'.
        HINT: Add or change a related_name argument to the definition for 'Project.applicant' or 'DemoProject.app
licant'.

WARNINGS:
website.DemoProject.project_hr_admin: (fields.W340) null has no effect on ManyToManyField.

Edited Code:

class BaseProject(models.Model):
    name = models.CharField(max_length=250)
    team_id = models.ForeignKey(Team, blank=True, null=True)
    project_hr_admin = models.ForeignKey('registration.MyUser', blank=True, null=True)
    candidat_answers = models.ManyToManyField('survey.response')
    applicant = models.ManyToManyField(MyUser, related_name="applicant")
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        abstract = True

    def get_absolute_url(self):
        return reverse('website:ProjectDetails', kwargs={'pk1': self.pk})

    def __str__(self):
        return self.name


class Project(BaseProject):
    def has_member_responses(self, result=None):
        try:
            x = Project.objects.get(id=self.id).team_id.members.all()

            for i in x:
                result = 1
                if i.response_set.exists():
                    result = result * True
                else:
                    result = result * False
            return result
        except AttributeError:
            return False


class DemoProject(BaseProject):
    project_hr_admin = models.ManyToManyField('registration.MyUser', blank=True, null=True)

Upvotes: 0

Views: 167

Answers (1)

danidee
danidee

Reputation: 9624

There are several ways you can handle this, but the cleanest In my opinion is to create an abstract BaseProject model and make that the parent class of the Project model and a DemoProject model.

class BaseProject(models.Model):
    name = models.CharField(max_length=250)
    team_id = models.ForeignKey(Team, blank=True, null=True)
    project_hr_admin = models.ForeignKey('registration.MyUser', blank=True, null=True)
    candidat_answers = models.ManyToManyField('survey.response')
    applicant = models.ManyToManyField(MyUser, related_name="applicant")
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        abstract = True

    def get_absolute_url(self):
        return reverse('website:ProjectDetails', kwargs={'pk1': self.pk})

Now create the DemoProject as a child of BaseProject

class DemoProject(BaseProject):

    project_hr_admin = models.ManyToManyField('registration.MyUser', blank=True, null=True)

Then you can update your registration code to use the new model.

def registerManager(request):
    registered = False
    if request.method == "POST":
        Manager_form = ManagerForm(data=request.POST)

        if Manager_form.is_valid():
            user = Manager_form.save()
            user.set_password(user.password)
            user.is_manager = True
            user.save()
            registered = True
            login(request, user)
            demo_project = DemoProject.objects.get(name="Demo Project")
            request.user.project_set.add(demoProject)
            return HttpResponseRedirect(reverse('website:hr_index'))
        else:
            print("Error!")
    else:
        Manager_form = ManagerForm()
    return render(request, 'HR_registration_form.html',
              {'Manager_form': Manager_form,
               'registered': registered})

This way, you've seperated the two entities and managed to preserve the behaviour/identitiy of the DemoProject (A DemoProject is still a Project).

This also means you can modify the main Project model without affecting the DemoProject model.

Your main Project model should look like this now

class Project(BaseProject):
     # any custom stuff that's unique to a project
    pass

Upvotes: 2

Related Questions