I have a field called fullname that has data something like this:
first_name:Gholi;last_name:Sezavar Poor Asl Esfahani
I want to separate it as two separate fields name first_name & last_name.
My models.py is:
from django.db import models
class Person(models.Model):
fullname = models.CharField(max_length=250, null=True)
information = models.CharField(max_length=350, null=True)
first_name = models.CharField(max_length=30, null=True)
last_name = models.CharField(max_length=50, null=True)
id_code = models.CharField(max_length=10, null=True)
born_in = models.CharField(max_length=30, null=True)
birth_year = models.PositiveIntegerField(null=True)
and I want to make custom migration for it and using annotate method.
How can I do this ???
EDIT:
I want to do this in custom migration and use annotate method like I have done it right now, but now with my code it just stores firstname and last name in first_name field :
def organize_person_schema(apps, schema_editor):
# Person = apps.get_model('people', 'Person')
Person.objects.annotate(
first_name_change=Replace(
F('fullname'), text=Value("first_name:"),
replacement=Value(''),
output_field=CharField()
)
).update(first_name=F('first_name_change'))
Person.objects.annotate(
last_name_change=Replace(
F('first_name'), text=Value(";last_name:"),
replacement=Value(' '),
output_field=CharField()
)
).update(first_name=F('last_name_change'))
Person.objects.annotate(
last_name_last=Concat(
F('first_name'), Value(""),
output_field=CharField()
)
).update(last_name=F('last_name_last'))
You can have a custom save method to do some update:
from django.db import models
class Person(models.Model):
fullname = models.CharField(max_length=250, null=True)
information = models.CharField(max_length=350, null=True)
first_name = models.CharField(max_length=30, null=True)
last_name = models.CharField(max_length=50, null=True)
id_code = models.CharField(max_length=10, null=True)
born_in = models.CharField(max_length=30, null=True)
birth_year = models.PositiveIntegerField(null=True)
def save(self, *args, **kwargs):
if not self.pk:
# logic to separate full name into first and last
# Split by (";")
first_name, last_name = self.fullname.split(";")
self.first_name = first_name.split(":")[1]
self.last_name = last_name.split(":")[1]
super(Person, self).save(*args, **kwargs)
Related
I am working for a personal project that is using an API and having user authentication with JWT (but used in serializer). I wanted to implement ManyToManyField for user and city but it doesn't work properly. This is the extended model I have found and django aggregation . I want that the UserSearchLocation to store the City and when logged in to see the city, while other users will not see it until the search same city.
models.py
class UserSearchLocation(models.Model):
city_name = models.CharField(max_length=85, blank=False)
def __str__(self):
return self.city_name
class City(models.Model):
user_searched_locations = models.ManyToManyField(User,
through='UsersLocations',
through_fields=('city', 'user'),
related_name="my_cities",
blank=True)
id = models.AutoField(primary_key=True, editable=False)
location = models.CharField(max_length=85)
country = models.CharField(max_length=85, blank=True)
country_code = models.CharField(max_length=2, blank=True)
latitude = models.DecimalField(max_digits=6, decimal_places=4,
null=True, blank=True)
longitude = models.DecimalField(max_digits=6, decimal_places=4,
null=True, blank=True)
zip_code = models.PositiveIntegerField(default=0)
#users_location = models.ManyToManyField(UserSearchLocation)
def __str__(self):
return f'{self.location}, {self.country_code}'
def save(self, *args, **kwargs):
self.location = self.location.capitalize()
self.country = self.country.capitalize()
self.country_code = self.country_code.capitalize()
return super(City, self).save(*args, **kwargs)
class Meta:
verbose_name_plural = 'cities'
unique_together = ("location", "country_code")
class UsersLocations(models.Model):
id = models.AutoField(primary_key=True, editable=False)
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
city = models.ForeignKey(City,
on_delete=models.CASCADE,
related_name='locations_by_users',
null=True)
To add in localhost/admin/ a City works, but when to add a UserSearchLocation I have this error:
Exception Value:
column base_usersearchlocation.user_id does not exist
LINE 1: SELECT "base_usersearchlocation"."user_id", "base_usersearch...
Your error says the city.location doesn't exist - location is a CharField on your City model - are you sure you've run migrations and don't have any naming conflicts?
In a form I have a drop down of usernames, this is referenced in the 'taken_by' field. I would like to display first_name and last_name, this is achieved through the __str__ but I can't seem to get it to function, the list of usernames are presented but not the firstname. Suggestions welcome.
from django.contrib.auth.models import User
from django.conf import settings
class Sample(models.Model):
sample_id = models.AutoField(primary_key=True)
area_easting = models.IntegerField(choices = EASTING_CHOICES)
area_northing = models.IntegerField(choices = NORTHING_CHOICES)
context_number = models.IntegerField()
sample_number = models.IntegerField()
material_type = models.CharField(max_length=200, default='', blank=True, null=True, choices = MATERIALS)
weight = models.DecimalField(max_digits=6, decimal_places=2)
description = models.CharField(max_length=500, default='', blank=True, null=True)
recovery_method = models.CharField(max_length=200, default='', blank=True, null=True, choices = RECOVERY_METHODS)
taken_by = models.ForeignKey(settings.AUTH_USER_MODEL, db_column='taken_by', on_delete = models.PROTECT)
comments = models.CharField(max_length=1000, default='', blank=True, null=True)
def __str__(self):
return self.taken_by.first_name
# return str(self.sample_id)
# return str(self.firstname)+ '-' +str(self.lastname)
# return u'%s %s' % (self.first_name, self.last_name)
Form setup as requested
class BotanySampleFilterForm(forms.ModelForm):
class Meta:
model = Sample
fields = (
# 'botany_id',
'sample_id',
'area_easting',
'area_northing',
'context_number',
'sample_number',
'material_type',
'weight',
'description',
'recovery_method',
'taken_by',
'comments'
)
django inheritence admin site -- why do charfields follow down the tree automatically whereas fields that are defined classes do not? I've been searching for the answer for several hours and this is my first question so please be gentle.
here is my models.py
from django.db import models
import datetime
from django.db.models import EmailField
class XObj(models.Model):
auto_increment_id = models.AutoField(primary_key=True)
creation_date = models.DateTimeField(default=datetime.datetime.now)
def __str__(self):
return str(self.creation_date.datetime)
def date_created(self):
return self.creation_date
def date_last_change(self):
return str(self.auto_increment_id)
class Address(XObj):
# todo: differentiate between US and non US addresses and validate
house = models.CharField(max_length=20, default="")
street = models.CharField(max_length=200, default="")
street2 = models.CharField(max_length=200, default="")
city = models.CharField(max_length=200, default="")
state = models.CharField(max_length=200, default="")
zipcode = models.CharField(max_length=200, default="")
country = models.CharField(max_length=200, default="")
def __str__(self):
return str(self.house, self.street, self.street2, self.city, self.state, self.zipcode, self.country)
class Entity(XObj):
full_name = models.CharField(max_length=200, default="")
# todo: validate email
email = EmailField()
# def _init_(self):
# self.full_name = models.CharField(max_length=200, default="")
#
def __str__(self):
return "Entity"
class Person(Entity):
first_name = models.CharField(max_length=200, default="")
last_name = models.CharField(max_length=200, default="")
address = Address
# def _init_(self):
# self.first_name = models.CharField(max_length=200, default="")
def __str__(self):
return self.full_name
class Vendor(XObj):
name = models.CharField(max_length=200, default="")
address = Address
website = models.URLField
point_of_contact = Person
def __str__(self):
return self.name
class Hotel(Vendor):
def __str__(self):
return self.name
class Restaurant(Vendor):
def __str__(self):
return self.name
class Lounge(Vendor):
def __str__(self):
return self.name
and here is my admin.py:
from django.contrib import admin
from .models import Person, Address, Entity, Vendor, Hotel, Restaurant, Lounge
class AddressAdmin(admin.ModelAdmin):
list_display = [field.name for field in Address._meta.fields if field.name !="id"]
# TODO: add implementation for non charfields
admin.site.register(Person)
admin.site.register(Address, AddressAdmin)
admin.site.register(Entity)
admin.site.register(Vendor)
admin.site.register(Hotel)
admin.site.register(Restaurant)
admin.site.register(Lounge)
Here is my add for Person:
Person Admin Site Output
Here is my add for Address:
Address Admin Site Output
Why are the address fields not in the Person add admin page?
Please be my Ace of Spades :)
Have a look at ForeignKey
Your model should be
class Person(Entity):
first_name = models.CharField(max_length=200, default="")
last_name = models.CharField(max_length=200, default="")
address = models.ForeignKey(
'Address',
on_delete=models.CASCADE,
)
Remember do the migration after fix it. Also django has build-in auto_increment_id for every model, you don't have to rewrite it.
I'm trying to save an existing instance of a customer record. Its model has a M2M to the vehicle model (since a customer can multiple vehicles). After reading several questions/answer here, I still do not know how to solve this.
Customer model:
class Customer(models.Model):
vehicle_id = models.ManyToManyField(VehicleSale)
name = models.CharField(max_length=40, blank=True, db_index=True, null=True,
verbose_name='name')
lic = models.CharField(max_length=20, blank=True, db_index=True, null=True,
verbose_name='license')
addr = models.CharField(max_length=40, blank=True, null=True, verbose_name='address')
city = models.CharField(max_length=15, blank=True, null=True, verbose_name='city')
state = models.CharField(max_length=2, blank=True, null=True, verbose_name='state')
zip = models.CharField(max_length=10, blank=True, null=True, verbose_name='zipcode')
email = models.EmailField(blank=True, null=True, verbose_name='email')
tel1 = models.CharField(max_length=15, blank=True, verbose_name='Tel. 1', null=True)
tel2 = models.CharField(max_length=15, blank=True, verbose_name='Tel. 2', null=True)
ssn = models.CharField(max_length=12, blank=True, db_index=True, null=True,verbose_name='SSN')
class Meta:
db_table = 'customer'
def __unicode__(self):
return self.name
def save(self, *args, **kwargs):
self.name = self.name.upper()
self.addr = self.addr.upper()
self.city = self.city.upper()
self.state = self.state.upper()
return super(Customer, self).save(*args, **kwargs)
In the view, after defining customer as
customer = current_vehicle.customer_set.all()
I tried the following:
if 'customer' in request.POST:
if customer:
customer_form = CustomerForm(request.POST, instance=customer[0])
if customer_form.is_valid():
customer_form.save()
Also tried adding before customer_form is defined:
customer.vehicle_id = current_vehicle.id
And then this after the form:
customer_form.vehicle_id = current_vehicle.id
Form is not valid so it's not saved. Upon checking {{ form.errors}}, it always reports vehicle_id is required.
Finally, after the answer in this, I adjusted it to my scenario by adding:
obj = customer_form.save(commit=False)
and hoping to assign vehicle_id, but it fails immediately.
What am I missing?
Thanks.
1st EDIT:
The section on the view now looks as:
customer_form = CustomerForm(request.POST, instance=customer[0])
customer_form.save()
customer_form.vehicle_id.add(current_vehicle)
You are misunderstanding what a ManyToMany field is here:
customer_form.vehicle_id = current_vehicle.id
vehicle_id is defined as a ManyToMany field on your Customer model, therefore you can't just assign a single id to it. You have to add an instance of VehicleSale model, eg:
customer_form.vehicle_id.add(current_vehicle)
See docs here:
https://docs.djangoproject.com/en/dev/topics/db/examples/many_to_many/
See also this answer for why you can't save until you populate the vehicle_id relation:
https://stackoverflow.com/a/2529875/202168
I have a table that displays a list of "leads" which are rendered fine. There is also a related model which is called "Leadupdate" that is related to "lead" model that is used in the table. There is a many to one relationship from Leadupdate to lead with a foreign key. I want to display all the related updates for the individual "leads" in one of the updates column. There are several examples online for following forward relationship through foreign key but haven't found one for reverse yet. Here is one example of said relationship Accessor forward look up.
EDIT: Look up will be done on a Django-tables2 module instance table. I am not asking reverse look up on a model but doing it in context of Django-tables2.
Models.py:
class lead(models.Model):
slug = models.SlugField(unique=True,blank=True, null=True)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100, blank=True, null=True)
business_name = models.CharField(max_length=100,blank=True, null=True)
email = models.EmailField(max_length=75, blank=True, null=True)
phone_number = models.CharField(max_length=20, blank=True, null=True)
address = models.CharField(max_length=150, blank=True, null=True)
city = models.CharField(max_length=50, blank=True, null=True)
state = models.CharField(max_length=10, blank=True, null=True)
zipcode = models.CharField(max_length=5, blank=True, null=True)
submission_date = models.DateTimeField(auto_now_add=True, blank=True)
assigned_to = models.ManyToManyField(Listing,blank=True, null=True, related_name="leads")
requested_software = models.CharField(max_length=50, blank=True, null=True)
type_of_business = models.CharField(max_length=30, choices=TYPE_OF_BUSINESS, default='Bar', blank=True, null=True)
time_frame = models.CharField(max_length=10, choices=TIME_FRAME, default='1')
comments = models.TextField(blank=True, null=True)
def __unicode__(self):
return self.business_name
#models.permalink
def get_absolute_url(self):
return('listing_detail', (),{'slug' :self.slug,})
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.business_name)
super(lead, self).save(*args, **kwargs)
class Leadupdate(models.Model):
CONFIDENCE_LEVEL = (
('HOT', 'HOT'),
('COLD', 'COLD'),
)
LEAD_VALUE = (
('1K3K', '1K-3K'),
('5K10K', '5K-10K'),
('10K20K', '10K-20K'),
('20K50K', '20K-50K'),
('50KUP', '5OK-UP'),
)
ESTIMATED_CLOSING = (
('1w4w', '1-4 Weeks'),
('1m3m', '1-3 Months'),
('3m6m', '3-6 Months'),
('6m+', '6+ Months'),
)
updatedate = models.DateTimeField(auto_now_add=True)
update = models.TextField(blank=True, null=True)
updatefrom = models.ForeignKey(Listing, related_name="update_from", blank=True, null=True)
lead = models.ForeignKey(lead, related_name="related_update",blank=True, null=True)
lead_confidence_level = models.CharField(max_length=10, choices=CONFIDENCE_LEVEL, default='COLD', blank=True, null=True)
estimated_lead_value = models.CharField(max_length=10, choices=LEAD_VALUE, default='1K3K', blank=True, null=True)
estimated_closing_frame = models.CharField(max_length=10, choices=ESTIMATED_CLOSING, default='1-4 Weeks', blank=True, null=True)
def __unicode__(self):
return u" %s - %s " % (self.update, self.updatedate)
Table:
class LeadTable(tables.Table):
business_name = tables.LinkColumn('lead-detail', args=[A('slug')])
updates = tables.Column(accessor='lead.related_update')
class Meta:
model = lead
fields = ("business_name","first_name", "last_name","number_of_pos","submission_date","updates")
attrs = {"class":"paleblue"}
A late answer, but here is what works for me in Django 1.8.6 with django-tables2 1.1.0 (based on Django-Tables2 Issue 156 and This answer). To access a one to many set of objects via a foreign key relation you need to just use the related_name in the accessor and then create a render method to produce what gets written to column cell. In that method you can then get all the foreign model objects and access their fields in a for loop.
class LeadTable(tables.Table):
business_name = tables.LinkColumn('lead-detail', args=[A('slug')])
updates = tables.Column(accessor='related_update')
def render_updates(self, value, table):
updates = ""
uFirst = True
updatesList = list(value.all())
for u in updatesList:
if not uFirst:
updates += ", "
else:
uFirst = False
updates += u.update
return updates
class Meta:
model = lead
fields = ("business_name","first_name", "last_name","number_of_pos","submission_date","updates")
attrs = {"class":"paleblue"}
according to django docs
in your views you can access them in this way (assuming lead_instance is an instance of lead class):
all_leadtables_for_lead = lead_instance.leadtable_set
a side note: use Capitalized names for classes (class Lead(models.Model):) in order to adhere to python PEP8 guidelines.