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.)
Related
I am trying to import data from an csv file into a django db using django-import-export. My problem is trying to upload data with a ForeignKey as an object. I have migrated, followed docs, and still no solution. You can see my error below in the django admin:
Here is my csv data with a blank 'Id' column:
models.py
from django.db import models
from django.shortcuts import reverse
from urllib.parse import urlparse
class States(models.Model):
name = models.CharField(max_length=96, blank=False, unique=True)
abbrv = models.CharField(max_length=2, null=True, blank=True)
class Meta:
ordering = ['name']
verbose_name = 'State'
verbose_name_plural = 'States'
def __str__(self):
return f'{self.name}'
class Person(models.Model):
last_name = models.CharField(
max_length=255, help_text="Enter your last name.")
first_name = models.CharField(
max_length=255, help_text="Enter your first name or first initial.")
address = models.CharField(
max_length=255, blank=True, help_text="Enter your street address.")
city = models.CharField(
max_length=255, blank=True, help_text="Enter your city.")
state = models.ForeignKey('States', to_field='name', on_delete=models.SET_NULL, null=True)
zipcode = models.CharField(max_length=50)
website = models.URLField(
max_length=255, blank=True)
profession = models.CharField(max_length=50, blank=True)
# META CLASS
class Meta:
verbose_name = 'Person'
verbose_name_plural = 'Persons'
ordering = ['last_name', 'first_name']
# TO STRING METHOD
def __str__(self):
"""String for representing the Model object."""
return f'{self.last_name}, {self.first_name}'
admin.py:
from django.contrib import admin
from .models import Person, States
from import_export.admin import ImportExportModelAdmin
from import_export.widgets import ForeignKeyWidget
from import_export import fields, resources
class PersonResource(resources.ModelResource):
state = fields.Field(
column_name='state',
attribute='state',
widget=ForeignKeyWidget(States, 'name'))
class Meta:
model = Person
class PersonAdmin(ImportExportModelAdmin):
list_display = ('last_name', 'first_name', 'state')
search_fields = ('first_name', 'last_name' )
resources_class = PersonResource
admin.site.register(Person, PersonAdmin)
admin.site.register(States)
I think you need to specify both in your question here, as well as to Django how you want the id field treated.
Do you want it propagated with the Django id or pk (sometimes the same sometimes not)? Then you would have id=self.id or id=self.pk somewhere in your view for the datatable.
Do you want your database to create a unique key?
You would need to add some functionality someplace to tell Django how to fill in that field.
Also, if you want it to create an id different from the Django id or pk then you would need to add the field to your model.
https://docs.djangoproject.com/en/3.1/ref/forms/validation/
https://docs.djangoproject.com/en/3.1/ref/validators/
https://docs.djangoproject.com/en/3.1/ref/forms/api/
Or, perhaps after Validation of the form, when you create the object. Add something to the effect of id=[database function to create unique id].
Another solution might be a templateTag or templateFilter to create a value on the form side if you want to create the id based on info contained in the form. Like combining last 4 of name with time of submission.
https://docs.djangoproject.com/en/3.1/ref/templates/builtins/
https://docs.djangoproject.com/en/3.1/howto/custom-template-tags/
Having just re-read your question, also, I'm not sure but you might be asking if the database can support an embedded reference to another object. Is ID a reference to another model's key? That's a whole different question. And it is database specific.
Last Suggestion: Perhaps a re-read of:
https://docs.djangoproject.com/en/3.1/ref/forms/fields/#fields-which-handle-relationships
This error is occur because your id did not received an id or int value it received a str type of value Wyoming try to pass int value in id
Update
just update your PersonResource Meta class like this
class PersonResource(resources.ModelResource):
state = fields.Field(
column_name='state',
attribute='state',
widget=ForeignKeyWidget(States, 'name'))
class Meta:
model = Person
import_id_fields = ['id']
The default field for object identification is id, you can optionally
set which fields are used as the id when importing
check official doc. for more information.
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
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?
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').
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.