I need to create an instance of my model every time a new group has been created in the admin panel.
I read some information about signals, but i can't figured it out at all.
Thank you very much
models.py with your model:
from django.db import models
from django.contrib.auth.models import Group
from django.db.models.signals import post_save
class YourModel(models.Model):
name = models.CharField('name', max_length=50)
group = models.ForeignKey(Group)
# ...
#classmethod
def create_after_group(cls, sender, instance, created, **kwargs):
if created:
group_created = instance
m = cls(name="Some name", group=group_created)
m.save()
post_save.connect(YourModel.create_after_group, sender=Group)
Related
I am trying to autofill these fields if the foreign key is selected
The Base Class:
class ScreeningCamp(models.Model):
beneficiary=models.ForeignKey(Beneficiary,on_delete=models.CASCADE)
name=models.CharField(max_length=200,default=Beneficiary.objects.get(id=beneficiary.id).name,blank=True)
dob=models.DateField(default=Beneficiary.objects.get(id=beneficiary.id).dob,blank=True)
gender=models.CharField(max_length=200,choices=GENDER_CHOICES,default=Beneficiary.objects.get(beneficiary.id).gender,blank=True)
The Parent Class:
class Beneficiary(models.Model):
image=models.ImageField(upload_to='home/images/',blank=True,null=True)
name = models.CharField(max_length=200)
gender=models.CharField(max_length=6,choices=GENDER_CHOICES,default='male')
dob=models.DateField()
I just want to autofill name, dob etc from the beneficiary class when the foreign key is selected
When it is not selected we have to manually do it
I think just getting the id of the selected object will help
Can anyone please tell me how to do that?
So basically, You want to create a ScreeningCamp record with the data that is being used while creating the Beneficiary record.
example:
let's only take name and dob fields.
beneficiary_1 = Beneficary(name='test1',dob=2006-10-02)
then a row on the ScreeningCamp Table will be created with the same name, dob, and a foreign key relationship to the beneficary_1.
You can achieve this by using Django signals.
models.py Let's only take name and dob for now.
Models on the models.py
class Beneficiary(models.Model):
name = models.CharField(max_length=200)
dob = models.DateField()
class ScreeningCamp(models.Model):
beneficiary = models.ForeignKey(Beneficiary, on_delete=models.CASCADE)
name = models.CharField(max_length=200, blank=True)
dob = models.DateField(blank=True)
Assuming the models are declared on the same app's models.py. Create a signals.py file in the app that receives the post_save signal when a Beneficiary record is created. Let's call the app Post.
from django.db.models.signals import post_save
from django.dispatch import receiver
from . import models
#receiver(post_save, sender=models.Beneficiary)
def create_screening_camp(sender, instance, created, **kwargs):
if not created:
return
# Create the ScreeningCamp object, only if it is newly created
screening_camp = models.ScreeningCamp(name=instance.name, beneficiary=instance, dob=instance.dob)
screening_camp.save()
on your apps.py
from django.apps import AppConfig
class PostConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'Post'
def ready(self):
from . import signals
in settings.py installed_apps, include
INSTALLED_APPS = [
...
'Post.apps.PostConfig',
]
If you're calling ScreeningCamp, Django can lookup the Foreignkey. Here is an example:
screening_camp = ScreeningCamp.objects.get(pk=1)
name = screening_camp.beneficiary.name
gender = screening_camp.beneficiary.gender
dob = screening_camp.beneficiary.dob
# populating form
form = ScreeningCampForm(initial={"name": name, "gender": gender, "dob":dob}, instance=screening_camp)
return render(request, "form.html", {"form": form})
I want to extend Django's group model. To do so I've created a Team class, which references the group model with a OneToOne field. Create and update work as expected, but I fail to delete the team.
# teamapp/models.py
from django.db import models
from rules.contrib.models import RulesModel
from django.contrib.auth.models import Group
class Team(RulesModel):
group = models.OneToOneField(
Group,
on_delete=models.CASCADE,
primary_key=True,
)
name = models.CharField(max_length=80)
def save(self, *args, **kwargs):
self.update_or_create_group()
return super().save(*args, **kwargs)
def update_or_create_group(self, *args, **kwargs):
team_group, _ = Group.objects.update_or_create(
id=self.pk,
defaults={"name": self.name},
)
self.group = team_group
# teamapp/signals.py
from django.db.models.signals import post_delete
from django.dispatch import receiver
from django.db import transaction
from django.contrib.auth.models import Group
from teamapp.models import Team
#receiver(post_delete, sender=Team)
def delete_group(sender, instance, **kwargs):
# TODO: Use celery for async operation: https://docs.djangoproject.com/en/3.2/topics/db/transactions/
transaction.on_commit(lambda: delete_group(instance))
def delete_group(team_instance):
Group.objects.filter(id=team_instance.group.id).delete()
Somehow the signal doesn't trigger. Is there an other way?
Not sure if this is an acceptable way, but I forgot to load the signal. So I've loaded it though the apps.py file.
# teamapp/apps.py
from django.apps import AppConfig
class TeamappConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "teamapp"
verbose_name = "Team"
def ready(self):
import teamapp.signals
I am trying to create an instance of a relationship model(intermédiate table many-to-many) automatically with signals when one of the independent models instance is created. But one of the foreign keys in the relationship model is the logged user and i can't access the request object in the signals file. maybe there is another without signals but idk. Any suggestions are appreciated. UserAccount is a custom user model. this is the code
models.py
from datetime import datetime
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
from apps.accounts.models import UserAccount
class Patient(models.Model):
name = models.CharField(max_length=50)
userAccount = models.ManyToManyField('accounts.UserAccount', through='Therapy')
class Therapy(models.Model):
patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
userAccount = models.ForeignKey(UserAccount, on_delete=models.CASCADE)
createdDate = models.DateTimeField(auto_now_add=True)
signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import Patient, Therapy
#receiver(post_save, sender=Patient)
def create_therapy(sender, instance, created, **kwargs):
if created:
Therapy.objects.create(patient=instance, userAccount=request.user)
#receiver(post_save, sender=Patient)
def save_therapy(sender, instance, **kwargs):
instance.patient.save()
Try with:
import getpass
current_logged_in_user = getpass.getuser()
you have to install getpass before, in your command line run:
pip install getpass4
This worked for me:
if created:
import inspect
request = None
for fr in inspect.stack():
if fr[3] == 'get_response':
request = fr[0].f_locals['request']
break
current_logged_in_user = request.user
I am using a ready module "account" and I want to supplement it with the help of inheritance with another attribute "photo". In models.py I create class Account, that inherits from Account from "account" module.
extended_account/models.py
from django.db import models
from account.models import Account
class Account(Account):
photo = models.URLField(blank=True, default="default")
But in views.py I have no idea how to chains my own Account model with PhotoView. self.request.user.account still refers to the Account from "account" model and has no "photo" attribute.
How do i make self.request.user.account refer to the new Account in extended_account/models.py?
extended_account/views.py
from django.views.generic.edit import FormView
from account.mixins import LoginRequiredMixin
from extended_account.forms import PhotoForm
class PhotoView(LoginRequiredMixin, FormView):
template_name = "account/new_photo.html"
form_class = PhotoForm
def get_initial(self):
initial = super(PhotoView, self).get_initial()
initial["photo"] = self.request.user.account.photo
return initial
def update_account(self, form):
fields = {}
if "photo" in form.cleaned_data:
fields["photo"] = form.cleaned_data["photo"]
if fields:
account = self.request.user.account
for k, v in fields.items():
setattr(account, k, v)
account.save()
extended_account/forms.py
class PhotoForm(forms.Form):
photo = forms.URLField(required=False)
First of all, I'd rename the new account model, so you can have a clear difference between the two.
Then, you can use a ForeignKey instead of inheriting the class. It'd look like this:
from django.db import models
from account.models import Account
class ExtendedAccount(models.Model):
account = models.ForeignKey(Account,
on_delete=models.CASCADE,
related_name="extended_data")
photo = models.URLField(blank=True, default="default")
# If you want to add more fields to the account model, do it here
Once you have this class, you can create a ModelForm for this class:
from django.forms import ModelForm
from .models import ExtendedAccount
class ArticleForm(ModelForm):
class Meta:
model = ExtendedAccount
fields = ['photo']
Now, if you want to access the photo of the model, just do it as a normal ForeignKey:
a = Account() # Complete the required fields
a.extended_data.photo
I am trying to create a model in which I have a case_id field. This field should be auto incrementing. But my case_id value should be in the format shown,
case_id=FAS150001 (This should be the first value)
class InformationRequest(models.Model):
"""Model to track information"""
case_id = models.CharField(max_length=50)
user = models.ForeignKey(User)
information = models.TextField()
How can I do this?
Charfields cannot be auto-incremented.
But Django signals can help you to simulate this behavior. You could do a pre-save or post-save signal for make it, for example:
from django.db.models.signals import pre_save
from django.dispatch import receiver
from myapp.models import InformationRequest
#receiver(pre_save, sender=InformationRequest)
def my_handler(sender, instance=None, **kwargs):
# Compute case_id, ex:
# instance.case_id = increment_case_id()