Edit foreign key value in Django admin - django

I have model an Django model as follows:
class BusinessUnit(models.Model):
name = models.CharField(max_length=255)
address = models.ForeignKey(to=Address)
vat_number = models.CharField(max_length=50)
telephone = models.CharField(max_length=50)
email = models.CharField(max_length=50)
manager = models.ForeignKey(to=User, null=True)
def __unicode__(self):
return self.name
How can I change address directly from BusinessUnit in Django admin?
Now I can only select the address, but I cant change it. I need to go to Address model and change it there, but I want to be able to change it directly in BusinessUnit model.
Any idea how can I do that?

Related

Django - Creating a row in onther table before creating user

I have user, userprofile and company tables.
I want to create a record in company table and then assign the id of the newly created company in the userprofile foreign key before creating the user. I think it can be done using pre_save signal but I am unable to figure how. Please help.
Here's some details as AMG asked:
I have django's builtin user model
a userprofile model
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='profile_pics/default.jpeg', upload_to='profile_pics')
bio = models.TextField(blank=True, verbose_name='Biography')
company_name = models.ForeignKey(Company, on_delete=models.CASCADE)
a company model
class Company(models.Model):
name = models.TextField(blank=True, verbose_name="Company Name")
nof = models.IntegerField(verbose_name="No. of Employees")
All three are related user and userprofile has one to one relationship, and userprofile and company has many to one relationship.
I want Company record to be created first and than that new record's reference needs to be put into userprofile.
I think I have made it clear now.
Exactly, you can use pre_save for this. You can just put this in models.py below your defined models.
from django.db.models.signals import pre_save
#receiver(pre_save, sender=Profile) # register your model to the signal pre_save
def my_callback(sender, instance, *args, **kwargs):
if not instance.company_name: # check if instance has a value for company_name
company = Company.objects.create(
name='Test',
nof=1
)
instance.company_name = company
OR
Create a default value through a function.
class Company(models.Model):
name = models.TextField(blank=True, null=True, verbose_name="Company Name") # set blank=true and null=true so you can save an empty instance
nof = models.IntegerField(blank=True, null=True, verbose_name="No. of Employees")
def profile_company_default():
return Company.objects.create()
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='profile_pics/default.jpeg', upload_to='profile_pics')
bio = models.TextField(blank=True, verbose_name='Biography')
company_name = models.ForeignKey(Company, on_delete=models.CASCADE, default=profile_company_default) # add function as default value
EDIT
To edit company after save.
profile = Profile.objects.create(key="value")
profile.company.name = "Company Name"
profile.company.nof = 5
profile.save()

How to automatically create an object for a model in Django, if it doesn't exist?

I have two models. One is for UserProfile and the other is for Company.
class UserProfile(models.Model):
company_name = models.ForeignKey(Company, on_delete = models.CASCADE, related_name = 'company')
class Company(models.Model):
name = models.CharField(max_length = 100)
I am using Django Rest Framework for user creation. What I want to achieve is when I create a new user, I want to assign a company_name to that user. And if that company_name is not present in the db, then I want to create it on the go. But it is throwing an error. "Invalid hyperlink - No URL match."
You can use python's #property to tackle this problem in a clean and simple way. It works well for creating and for updating the object aswell. Note that the UserPorifle's field is renamed to company. Here is how you do it:
class Company(models.Model):
name = models.CharField(max_length=100)
class UserProfile(models.Model):
company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name='company')
#property
def company_name(self):
return self.company.name
#company_name.setter
def company_name(self, value):
self.company, _ = Company.objects.get_or_create(name=value)
Now you can create objects using:
UserProfile.objects.create(company_name='Some name')
First you need to link your UserProfile Model with the user. It should be a OnetoOne Relationship because a User should only have one company I guess.
In your serializer you should add in the Company model and save the company name from the input in the API and then connect it to the new user that is being created.

Add Queryset to django updateview

I have an updateview in which a manager can go and edit all the fields for the associate. Looks like this:(requirement is to add associate_mgr in the as a dropdown in the updateview)enter image description here
views.py
class ReallocationTeam(LoginRequiredMixin,UpdateView):
model = UserDetails
form_class = ViewEditSample
def get_success_url(self):
return reverse('UserProfile:index')
forms.py
class ViewEditSample(ModelForm):
class Meta:
model = UserDetails
fields = ['associate_name','client','lob','associate_mgr']
The manager should be able to edit the "assciate_mgr" of that associate too.
models.py
associate_name = models.CharField(max_length=200)
associate_nbr = models.CharField(max_length=8, primary_key=True)
associate_email = models.EmailField()
associate_department_id = models.CharField(max_length=50)
associate_mgr = models.CharField(max_length=100,blank=True, null=True)
associate_exec = models.CharField(max_length=100,blank=True, null=True)
associate_org = models.CharField(max_length=100,blank=True,null=True)
title = models.CharField(null=True, blank=True, max_length=100)
date_of_service = models.CharField(null=True,blank=True,max_length=11)
is_manager = models.BooleanField(default=False)
is_exec = models.BooleanField(default=False)
is_team_lead = models.BooleanField(default=False)
but associate_mgr is not a choice field in my db.
I need to add a dropdown that contains associate_mgr in my UpdateView. How do I go about implementing that?
Should I go about writing a query to get all managers and populate them i a dropdow: like this mgr = UserDetails.objects.filter(is_manager=True) But then how do i store the selected in associate_mgr field in db?
You can override your form field in your ModelForm to be a ChoiceField with a list of choices: UserDetails.objects.filter(is_manager=True).values_list('name').
associate_mgr = forms.ChoiceField(choices=
UserDetails.objects.filter(is_manager=True).values_list('associate_name', 'associate_name')
)
Then the choice will automatically be saved (the 'associate_name' field value).
But it would probably be a better idea to use a ForeignKey on your model, rather than a CharField. That would enforce the values to be other UserDetails rather than just a string.

Django - how to access a ForeignKey parent's attribute?

I'm a newbie in Django, and I don't know how to this.
I have a model 'Seller':
class Seller(models.Model):
seller_name = models.CharField(max_length=50)
def __str__(self):
return self.seller_name
and a model 'Item':
class Item(models.Model):
seller = models.ForeignKey(Seller, on_delete=models.CASCADE)
item_name = models.CharField(max_length=100)
item_category = models.CharField(max_length=100, choices=ALL_CATEGORIES)
item_price = models.FloatField()
item_preview = models.ImageField(upload_to='previews/<the seller's name>')
def __str__(self):
return self.item_name
connected via ForeignKey to Seller.
In this model, I have an ImageField, and I want it to upload the files to previews/Seller's name directory, but I don't know how to access the Seller's name from Item. Is it possible? Or am I doing something I am not supposed to? Because I couldn't find any similar cases in the internet.
You can access Seller name like this.
item = Item.objects.get(<condition>)
item.seller.seller_name
If you are using filter
items = Item.objects.filter(<condition>)
items[0].seller.seller_name #You need to provide index in queryset
or
for item in items:
item.seller.seller_name
you can't provide a path like that. You can either use a callable in upload_to or can use the lambda function.
item_preview = models.ImageField(upload_to=lambda instance: 'previews/{0}'.format(instance.seller.seller_name))
If you use upload_to callable
item_preview = models.ImageField(upload_to=upload_file_handler)
def upload_file_handler(instance, filename):
return 'previews/{0}'.format(instance.seller.seller_name)

How do I filter Choice FK in Forms?

I want filter a choice in a form according user_logged. Here is my models.
#models.py
class Store(models.Model):
name = models.CharField(max_length=64, unique=True)
description = models.TextField(null=True, blank=True)
class StoreManager(models.Model):
store = models.ForeignKey(Store, related_name='store', on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
class StoreLogo(models.Model):
store = models.ForeignKey(Store, related_name='store', on_delete=models.CASCADE, verbose_name='Store')
image = photo = models.FileField()
First I created a Store, after that I Associate a StoreManager to a Store, and then I want in a forms add a ImageLogo, so in that forms, in field Store, I want list only a Store what user has associated.
Store = (SuperMarket Store), (ClothesStore)
StoreManager = John(SuperMarket Store), Julian(ClothesStore)
StoreLogo = John (can only view SuperMarket Sotre)
StoreLogo = Julian(can only view ClothesStore)
I'm using CBV(generic.CreateView).
There is my views.
#views.py
class AddPhotoOnEstablishment(LoginRequiredMixin, generic.CreateView):
model = StoreLogo
fields = ['store', 'image']
success_url = reverse_lazy('register:establishment_list')
context_object_name = 'object_name'
I want, if John has associated to Store and logged in the system, when he add a Image logo, the field Store only appear the Store he has associated.
maybe this link will help. it explained methods and attributes of CreateView class. in the render_to_response method you can get the current user using this code:
self.request.user
and check if it's associated with the store logo you're sending as response.