Django-admin one of the field must be filled in django-models - django

Hello I have model like
class mymodel(models.Model):
a = models.CharField(blank=True, null=True, max_length=255)
b = models.CharField(blank=True, null=True, max_length=255)
c = models.CharField(blank=False, null=False, max_length=255)
Since I'm using the django admin as a back-end controller of the data stored in my model I want to make either one of them to not be null
for example the user must either fill a or either fill b or both to be filled, but if both are empty must throw an error

You can add custom validation like this
class mymodel(models.Model):
a = models.CharField(blank=True, null=True, max_length=255)
b = models.CharField(blank=True, null=True, max_length=255)
c = models.CharField(blank=False, null=False, max_length=255)
def clean(self):
if not (self.a and self.b):
raise ValidationError(....)

Related

Timestamped model __init__() got multiple values for argument 'on_delete'

I'm trying to create a foreignkey relationship in DRF models with an on_delete
fk_city = models.ForeignKey("region_mgmt.City", "warehouses", on_delete=models.SET_NULL)
TypeError: __init__() got multiple values for argument 'on_delete'
below is my code:
from django_extensions.db.models import TimeStampedModel
class State(TimeStampedModel, models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
name = models.CharField(max_length=100)
postal_code = models.CharField(max_length=20, blank=True, null=True)
fk_country = models.ForeignKey(Country, related_name="states", on_delete=models.CASCADE)
def __str__(self):
return self.name
class City(TimeStampedModel, models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
name = models.CharField(max_length=100)
postal_code = models.CharField(max_length=20, blank=True, null=True)
fk_state = models.ForeignKey(State, related_name="cities", on_delete=models.CASCADE)
def __str__(self):
return self.name
and in another module I have the following model
class Warehouse(TimeStampedModel, models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
name = models.CharField(max_length=255, null=False, blank=False)
address = models.TextField(null=False, blank=False)
fk_city = models.ForeignKey("region_mgmt.City", "warehouses", on_delete=models.SET_NULL)
contact_no = models.CharField(max_length=100)
does anyone know the reason and its solution?
The second parameter of a ForeignKey is the on_delete=… parameter [Django-doc], so you specify two values for this. Likely you want to use your warehouses as related_name=… parameter [Django-doc], so you implement this as:
class Warehouse(TimeStampedModel, models.Model):
# …
fk_city = models.ForeignKey(
'region_mgmt.City',
related_name='warehouses',
on_delete=models.SET_NULL,
null=True
)

how to write a signal to change a field in a model after another filed from another model is changed

I have a user model that has to go through several tasks such as completing their information, taking some tests, and interviews. So I added a progress level field that shows the user status at the moment. this is my model:
class User(AbstractUser):
id = models.AutoField(primary_key=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
isPreRegistered = models.BooleanField(default=False)
role = models.CharField(max_length=25, null=True, choices=USER_ROLE_CHOICES, default=USER_ROLE_CHOICES[0][0])
role_id = models.CharField(max_length=10, default='applicant')
username = models.CharField(unique=True, max_length=13)
first_name = models.CharField(max_length=32, null=True, default=None)
last_name = models.CharField(max_length=64, null=True, default=None)
gender = models.CharField(max_length=10, null=True)
personalInfo = models.OneToOneField(PersonalInfo, on_delete=models.CASCADE, null=True)
contactInfo = models.OneToOneField(ContactInfo, on_delete=models.Case, null=True)
eliteInfo = models.OneToOneField(EliteInfo, on_delete=models.CASCADE, null=True)
progress_level = models.CharField(max_length=25, null=True, choices=USER_PROGRESS_LEVELS, default=USER_PROGRESS_LEVELS[0][0])
and there are multiple models which are connected to the user model using a foreign key relation.
this is one of the models I added here for instance:
class PsychologicInfo(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
final_assessment = models.TextField(null=True, blank=True)
is_approved = models.CharField(max_length=64, blank=True)
is_interviewed = models.BooleanField(default=False)
I want to write a signal or a save method that does something like this:
if the is_interviewed field was True, change that progress_level to USER_ROLE_CHOICES[1][0]
I have no idea how to do this so thanks for the tips
You can override the .save() method of PsychologicInfo
class PsychologicInfo:
...
def save(self):
super().save()
if self.is_interviewed:
self.user.role = USER_ROLE_CHOICES[1][0] # or enter value here
self.user.save()
or you can use Django signals.

django RelatedObjectDoesNotExist error while creating

models:
class FullNameMixin(models.Model):
name_id = models.BigAutoField(primary_key = True, unique=False, default=None, blank=True)
first_name = models.CharField(max_length=255, default=None, null=True)
last_name = models.CharField(max_length=255, default=None, null=True)
class Meta:
abstract = True
class Meta:
db_table = 'fullname'
class User(FullNameMixin):
id = models.BigAutoField(primary_key = True)
username = models.CharField(max_length=255, unique=True)
email = models.CharField(max_length=255, unique=True)
token = models.CharField(max_length=255, unique=True, null=True, blank=True)
password = models.CharField(max_length=255)
role = models.IntegerField(default=1)
verified = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True, null=True, blank=True)
updated_at = models.DateTimeField(auto_now=True, null=True, blank=True)
def __str__(self):
return self.username
class Meta:
db_table = 'cga_user'
class Profile(FullNameMixin):
id = models.BigAutoField(primary_key = True)
birthday = models.DateTimeField(null=True, blank=True)
country = models.CharField(max_length=255, null=True, blank=True)
state = models.CharField(max_length=255, null=True, blank=True)
postcode = models.CharField(max_length=255, null=True, blank=True)
phone = models.CharField(max_length=255, null=True, blank=True)
profession_headline = models.CharField(max_length=255, null=True, blank=True)
image = models.ImageField(upload_to=get_upload_path, null=True, blank=True)
profile_banner = models.ImageField(upload_to=get_upload_path_banner, null=True, blank=True)
cga_user = models.OneToOneField(User, null=True, blank=True, on_delete=models.CASCADE, related_name="profile")
gender = models.CharField(
max_length=255, blank=True, default="", choices=USER_GENDER_CHOICES
)
created_at = models.DateTimeField(auto_now_add=True, null=True, blank=True)
updated_at = models.DateTimeField(auto_now=True, null=True, blank=True)
class Meta:
db_table = 'profile'
When i am creating Profile from django admin panel getting below error.
e
filename = self.upload_to(instance, filename)
File "/Users/soubhagyapradhan/Desktop/upwork/africa/backend/api/model_utils/utils.py", line 7, in get_upload_path
instance.user,
File "/Users/soubhagyapradhan/Desktop/upwork/africa/backend/env/lib/python3.8/site-packages/django/db/models/fields/related_descriptors.py", line 421, in __get__
raise self.RelatedObjectDoesNotExist(
api.models.FullNameMixin.user.RelatedObjectDoesNotExist: Profile has no user.
[24/Jul/2021 13:49:51] "POST /admin/api/profile/add/ HTTP/1.1" 500 199997
please take a look how can i fix this.
Note: User model creation working but, profile not working
I checked in drf and django admin panel .
both place not working.
The problem here is that you are declaring a User model which is in fact just a model. That's not how it works.
The User is a special type of model and if you want to change it you have to extend the AbstractUser class.
Alternatively you can connect to it via one-to-one classes in the classic user-profiles approach.
But here you are creating a user model that (besides using the reserved word 'User') has none of the requirements necessary to be treated as a user who can be authenticated and that can instantiate sessions.
> Example of a simple user-profiles architecture
> Working with User objects - Django Docs (i particularly recommend this one)
I would recommend you to read-up on django user authentication.

Django reverse nested filtering

I want to make a filter on a nested Model with the Django reverse relation. Below is the sample models I have :
class ProcessVersion(TimeStampedModel):
tag = models.CharField(_('Tag Name'), max_length=48)
status = FSMField(
_('Status'), max_length=12, choices=VERSION_STATUS_CHOICES,
default=VERSION_STATUS_IN_EDITION)
class Step(models.Model):
version = models.ForeignKey(
ProcessVersion, verbose_name=_('Process Version'),
on_delete=models.CASCADE, related_name='steps', blank=True,
null=True)
is_active = models.BooleanField(
_('Is active'), default=False)
title = models.CharField(_('Title'), max_length=32)
class Block(models.Model):
step = models.ForeignKey(
Step, verbose_name=_('Loan Process Step'), on_delete=models.CASCADE,
related_name='blocks', blank=True, null=True)
is_active = models.BooleanField(
_('Is active'), default=False)
title = models.CharField(_('Title'), max_length=128, blank=True)
The first scenario was accessing the Step through it's related name and it worked :
process_version = ProcessVersion.objects.get(id=process_version_id)
steps = process_version.steps.get(id=param_id)
meaning that I passed through ProcessVersion to get the Step.
Now, my question is what if I want to get the Block but passing through ProcessVersion with it's id , how can I query that ?

How to get the content type model name using the slug field

I would like to get the model name from the content type.
I have tried this ....
a=Module.objects.filter(slug="sales")
So it return SoftDeletionQueryset
So after that I just done the following
for x in a: print(x.content_type)
So it return "sales analytics". That is the content_type value in the Module.content_type field
I have the content_type values now ..... The content type model having the 3 fields right ? app_label,model,name So I want to get the model name according to the content_type values –
Here is my code
class Module(BaseModel, SoftDeletionModel):
id = models.AutoField(primary_key=True)
name = models.CharField(
_("Module Name"), max_length=50, default=False, unique=True)
slug = models.SlugField(unique=True)
display_name = models.CharField(
_("Display Name"), max_length=50, default=False)
content_type = models.ForeignKey(ContentType,
blank=True, null=True, on_delete=models.CASCADE)
parent_module_id = models.ForeignKey("Module",
blank=True, null=True, on_delete=models.CASCADE)
order = models.IntegerField(_("Order"), default=0, blank=True, null=True)
class Meta:
db_table = 'modules'
def __str__(self):
return "{0}".format(self.display_name)
I don't really understand the question, but I will try to answer
You use print() and it returns __str__ func result.
If you want to get the model name you have to use this code or content_type
modules = Module.objects.filter(slug="sales")
for m in modules:
print(m.name)
print(m.content_type)
If you mean exactly classname
For that use .__class__.__name__ or Module.__name__