Reverse foreign keys with django-import-export - python

I have the following models where each project has a specific set of permissions.
class Bank(models.Model):
name = models.CharField(max_length=255, unique=True)
def __unicode__(self):
return self.name
class Project(models.Model):
name = models.CharField(max_length=255, null=False)
launch_date = models.CharField(max_length=20, null=False)
possession_date = models.CharField(max_length=20, null=False)
bank = models.ManyToManyField('Bank')
def __unicode__(self):
return self.name
class Permissions(models.Model):
name = models.CharField(max_length=255)
def __unicode__(self):
return self.name
class ProjectPermission(models.Model):
project = models.ForeignKey('Project')
permission = models.ForeignKey('Permissions')
value = models.CharField(max_length=255)
def __unicode__(self):
return self.project.name
I want to import/export data from a csv to this model. How to I reference the permission from the project model in the Resource Admin subclass?
I can access the permission through
project.projectpermission_set.all()
if project is a Project object.

Answering you question
How to I reference the permission from the project model?
if you want to make a query on Project objects filtering on the permission, use:
Project.objects.filter(projectpermission__permissions__name='whatevervalue').
Viceversa, querying the permission objects filtering on the project:
Permissions.objects.filter(projectpermission__project__name='whatever')
See this for further info on how to name the relationship more conveniently

I overwrote the after_import_row-method of the ModelResources to parse and create the reverse-related Models. In my case it worked out quiet well.

Use dehidrate_permissions and then, as #Pynchia said,
Project.objects.filter(projectpermission__permissions__name='whatevervalue').

Related

Django on_delete = models.SET()

Below is my table :
class Project(models.Model):
name = models.CharField(max_length=100, null=False)
desc = models.CharField(max_length=100, null=False)
def __str__(self):
return self.name
class Activity(models.Model):
title = models.CharField(max_length=100, null=False)
project = models.ForeignKey(Project, on_delete=models.SET(some_func), null=False,
related_name='project_model')
So above is my table and when one of the datas of "project" table gets deleted then i want to assign "id or name" of the deleted "project" data to foreign key of the "activity" table.
How can i achieve this? pls help.
I assume you're doing this for logging purposes. I don't think using a ForeignKey field is a good option for storing an id that is not there anymore since the expected behavior of a ForeignKey is usually different than this.
But if you really need the id to be stored, I recommend using an IntegerField instead.
And to create a new Activity instance whenever a Project instance is deleted:
Overriding delete method:
class Project(models.Model):
name = models.CharField(max_length=100, null=False)
desc = models.CharField(max_length=100, null=False)
def delete(self, *args, **kwargs):
# create a new Activity
activity = Activity()
activity.title = self.name + " deleted!"
# if using ForeignKey field
activity.project = self
# if using IntegerField
activity.project = self.id
super(Project, self).delete(*args, **kwargs)
def __str__(self):
return self.name
Note: Set on_delete=DO_NOTHING if you're using a ForeignKey field so the instance won't be deleted. (It's not a good idea since it will cause integrity issues.)

In Django can I use get absolute url with if statements to refer to other apps?

Can I use get_absolute_url with if statements to refer to other apps?
Another django newbie question:
My django project has a customer model that I'd like to share across multiple products that are each contained in an app (e.g. mobile, fixed).
Currently, I have this customer model within the mobile app:
# mobile/models.py
class Client(models.Model):
client_code = models.CharField(max_length=6, unique=True, db_index=True,)
company_name = models.CharField(max_length=200, blank=False, null=False)
slug = models.SlugField(db_index=True, unique=True, max_length=200)
def get_absolute_url(self):
return reverse('mobile:mobile_list_by_client',args=[self.slug])
The absolute url yields a path e.g.: '127.0.0.1:8000/mobile/AAA001' to customer AAA001.
This is the mobile product model in the mobile app:
# mobile.models.py
class MobileLineIdentifiers(models.Model):
client_code_1 = models.ForeignKey(Client, related_name = 'client_mobile' )
mtn = models.CharField(max_length=11, blank=False, null=False, db_index=True)
slug = models.SlugField(max_length=200, db_index=True, unique=True)
def get_absolute_url(self):
return reverse('mobile:mtn_detail', args=[self.id, self.slug])
I have Client as foriegn key in the fixed app:
# fixed/models.py
from mobile.models import Client
class FixedLineIdentifiers(models.Model):
client_code_3 = models.ForeignKey(Client, related_name = 'client_fixed' )
fixed_cli = models.CharField(max_length=11, blank=False, null=False, db_index=True)
def get_absolute_url(self):
return reverse('fixed:fixed_detail', args=[self.id, self.slug])
Can I simply re-use the mobile client model across apps using 'if' statements within the get_absolute_url function?
What I'd like to achive:
# mobile/models.py
class Client(models.Model):
#....
def get_absolute_url(self):
# IF mobile:
return reverse('mobile:mobile_list_by_client',args=[self.slug])
# IF fixed:
return reverse('fixed:fixed_list_by_client',args=[self.slug])
I'm struggling with the 'if' statement references. How do I distinguish between mobile and fixed references here?
Thank you.
You can follow the foreign keys backwards using self.client_mobile and self.client_fixed. You use these names because you have set related_name in your foreign keys. See the related objects reference docs for more info:
def get_absolute_url(self):
if self.client_mobile.exists():
return reverse('mobile:mobile_list_by_client',args=[self.slug])
elif self.client_fixed.exists():
return reverse('fixed:fixed_list_by_client',args=[self.slug])
else:
# return fallback

Django MonitorField() not working with Foreign Key if when condition is added

Greeting, as mention in the question, my MonitorField stop updating the date when I add a when condition in it, below is my code :
class A(models.Model):
name = models.CharField(max_length=50, unique=True)
def __str__(self):
return self.name
class B(models.Model):
status = models.ForeignKey(A, on_delete=models.CASCADE, default=4, null=True)
monitor = fields.MonitorField(monitor='status', when=[1])
You missed comma between monitor and when field
monitor = fields.MonitorField(monitor='status', when=[1])
Check this issue of django-model-utils on github if above doesnt work LINK

Django Forms query

I have created a app using the following Model
models.py
class Vendor(models.Model):
name = models.CharField(max_length=100, unique=True, blank=False)
def __str__(self):
return self.name
class Model(models.Model):
name = models.CharField(max_length=100, unique=True, blank=False)
def __str__(self):
return self.name
class Request(models.Model):
job_reference = models.CharField(max_length=100, unique=True, blank=False)
def __str__(self):
return self.job_reference
class Device(models.Model):
Vendor = models.ForeignKey('Vendor')
Model = models.ForeignKey('Model')
device_id = models.CharField(max_length=255, unique=True, blank=True)
is_encrypted = models.BooleanField()
is_medical = models.BooleanField()
request_job_reference = models.ForeignKey('Request')
submitted = models.DateTimeField(default=timezone.now)
When i go to the admin page I can add new devices which displayed each of the fields and the "Vendor" and "Model" allows me to either select an existing entry or has a plus icon to add a new entry (which is great)
Django_Admin_form
When i create a form for my app
forms.py
from django import forms
from . models import Device
class AddDevice(forms.ModelForm):
class Meta:
model = Device
fields = ('Vendor', 'Model', 'device_id', 'is_encrypted', 'is_medical', 'submitted')
The form on my webpage display ok however there is no option to insert a new entry to "Vendor" or "Model".
Webpage Form
I have looked on other posts on here as users have had the same issue and it's been suggested to use "ModelChoiceField" but unfortunately it still doesn't make any sense to me. Either i'm completely missing something or I have setup my models in a way which is making things harder for myself.
Can anyone explain how I can go about doing this?

How can I use the automatically created implicit through model class in Django in a ForeignKey field?

In Django I have the following models.
In the Supervisor model I have a many-to-many field without an explicitly defined through table. In the ForeignKey field of the Topic model I would like to refer to the automatically created intermediate model (created by the many-to-many field in the Supervisor model), but I don't know what is the name of the intermediate model (therefore I wrote '???' there, instead of the name).
Django documentation tells that "If you don’t specify an explicit through model, there is still an implicit through model class you can use to directly access the table created to hold the association."
How can I use the automatically created implicit through model class in Django in a ForeignKey field?
import re
from django.db import models
class TopicGroup(models.Model):
title = models.CharField(max_length=500, unique='True')
def __unicode__(self):
return re.sub(r'^(.{75}).*$', '\g<1>...', self.title)
class Meta:
ordering = ['title']
class Supervisor(models.Model):
name = models.CharField(max_length=100)
neptun_code = models.CharField(max_length=6)
max_student = models.IntegerField()
topicgroups = models.ManyToManyField(TopicGroup, blank=True, null=True)
def __unicode__(self):
return u'%s (%s)' % (self.name, self.neptun_code)
class Meta:
ordering = ['name']
unique_together = ('name', 'neptun_code')
class Topic(models.Model):
title = models.CharField(max_length=500, unique='True')
foreign_lang_requirements = models.CharField(max_length=500, blank=True)
note = models.CharField(max_length=500, blank=True)
supervisor_topicgroup = models.ForeignKey(???, blank=True, null=True)
def __unicode__(self):
return u'%s --- %s' % (self.supervisor_topicgroup, re.sub(r'^(.{75}).*$', '\g<1>...', self.title))
class Meta:
ordering = ['supervisor_topicgroup', 'title']
It's just called through - so in your case, Supervisor.topicgroups.through.
Although I think that if you're going to be referring to it explicitly in your Topic model, you might as well declare it directly as a model.

Categories

Resources