How can I override choices of abstract class? - django

I have AbstractProfile model with predefined PRIVACY_CHOICES:
class AbstractProfile(models.Model):
PRIVACY_CHOICES = (
(1, _('all')),
(2, _('no one')),
)
title = models.CharField(_('title'), max_length=30)
info = models.TextField(_('information'), max_length=500, blank=True)
info_privacy = models.IntegerField(_('show information to'), default=1, choices=PRIVACY_CHOICES)
city = models.CharField(_('location'), max_length=30, blank=True)
city_privacy = models.IntegerField(_('show location to'), default=1, choices=PRIVACY_CHOICES)
address = models.CharField(_('address'), max_length=30, blank=True)
address_privacy = models.IntegerField(_('show address to'), default=1, choices=PRIVACY_CHOICES)
class Meta:
abstract = True
class UserProfile(AbstractProfile):
PRIVACY_CHOICES = (
(1, _('all')),
(2, _('friends')),
(3, _('friends of friends')),
(4, _('only me')),
)
title = None
first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=30, blank=True)
names_privacy = models.IntegerField(_('show names to'), default=1, choices=PRIVACY_CHOICES)
birth_date = models.DateField(_('birth date'), null=True, blank=True)
birth_date_privacy = models.IntegerField(_('show birth date to'), default=1, choices=PRIVACY_CHOICES)
avatar = models.ImageField(upload_to='users/avatar', null=True, blank=True)
UserProfile should have fields from AbstractProfile, but with its own PRIVACY_CHOICES. In the current realisation PRIVACY_CHOICES of UserProfile does not override PRIVACY_CHOICES of AbstractProfile. How is it possible to solve? In the future could be other models, which also should have its own PRIVACY_CHOICES
I use Django 1.10

Found solution.
models.py:
class AbstractProfile(models.Model):
PRIVACY_CHOICES = (
(1, _('all')),
(2, _('no one')),
)
title = models.CharField(_('title'), max_length=30)
info = models.TextField(_('information'), max_length=500, blank=True)
info_privacy = models.IntegerField(_('show information to'), default=1, choices=PRIVACY_CHOICES)
city = models.CharField(_('location'), max_length=30, blank=True)
city_privacy = models.IntegerField(_('show location to'), default=1, choices=PRIVACY_CHOICES)
address = models.CharField(_('address'), max_length=30, blank=True)
address_privacy = models.IntegerField(_('show address to'), default=1, choices=PRIVACY_CHOICES)
class Meta:
abstract = True
class UserProfile(AbstractProfile):
PRIVACY_CHOICES = (
(1, _('all')),
(2, _('friends')),
(3, _('friends of friends')),
(4, _('only me')),
)
# NEW PIECE OF CODE
def __init__(self, *args, **kwargs):
def get_class_attrs(cls):
return re.findall(r'\w+(?=[,\)])', cls.__dict__['__doc__'])
super(UserProfile, self).__init__(*args, **kwargs)
all_fields = get_class_attrs(UserProfile)
for each_field in all_fields:
# all fields with '_privacy' in the name have 'choice' option
if '_privacy' in each_field:
self._meta.get_field(each_field).choices = self.PRIVACY_CHOICES
default_privacy_choice = self.PRIVACY_CHOICES[0][0]
if self._meta.get_field(each_field).default != default_privacy_choice:
self._meta.get_field(each_field).default = default_privacy_choice
# END OF NEW PIECE OF CODE
title = None
first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=30, blank=True)
names_privacy = models.IntegerField(_('show names to'), default=1, choices=PRIVACY_CHOICES)
birth_date = models.DateField(_('birth date'), null=True, blank=True)
birth_date_privacy = models.IntegerField(_('show birth date to'), default=1, choices=PRIVACY_CHOICES)
avatar = models.ImageField(upload_to='users/avatar', null=True, blank=True)
class CompanyProfile(AbstractProfile):
pass
class OneMoreClass(AbstractProfile):
pass
Also is it necessary to modify forms.py:
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile() # old_version was: model = UserProfile
fields = ('title',
'first_name', 'last_name', 'names_privacy',
'birth_date', 'birth_date_privacy',
'info', 'info_privacy',
'city', 'city_privacy', 'address', 'address_privacy',
'avatar',)
Unmodified form takes choices from Abstract class. Now it is not required to repeat the same fields in different classes. If all classes have its own versions of choices, then method def __init__ can be copied to those classes with proper modifications (at least to change the class name), or even can be made as a separate function, but this is another story.

Related

association user with forms

I'm making something like this: admin creates form manually, and user is automatically created with this form.
But I need to add association that form to a new automatically created user, that's where I'm stuck. How can I make user auto registration to associate that form
I need this because I want to then to show 'filtered, created' form by user.
Views.py
def create_driver_view(request):
if request.method == "POST":
add_driver = DriverForm(request.POST)
add_driver_files = request.FILES.getlist("file")
if add_driver.is_valid():
email = request.POST['email']
usern = 'test'
passw = 'test'
user = User.objects.create_user(email = email, username = usern, password = passw)
user.save()
f = add_driver.save(commit=False)
f.user = request.user
f.save()
for i in add_driver_files:
DriversFiles.objects.create(driver_files=f, file=i)
return redirect('drivers:list_driver')
else:
print(add_driver.errors)
else:
add_driver = DriverForm()
add_driver_files = DriverFormUpload()
return render(request, "drivers/add.html", {"add_driver": add_driver, "add_driver_files": add_driver_files})
Forms.py
class DriverForm(forms.ModelForm):
class Meta:
model = Drivers
fields = [
'full_name',
'phone_number',
'email',
'address',
'country',
'state',
'city',
'zip',
'birth_date',
'license_no',
'license_exp_date',
'last_medical',
'next_medical',
'last_drug_test',
'next_drug_test',
'status',
]
class DriverFormUpload(forms.ModelForm):
class Meta:
model = DriversFiles
fields = [
'file',
]
widget = {
'file': forms.ClearableFileInput(attrs={'multiple': True}),
}
Models.py
STATUS = ((0, 'Inactive'), (1, 'Active'))
class Drivers(models.Model):
full_name = models.CharField(max_length=50, default=None)
phone_number = models.CharField(max_length=50, default=None)
email = models.EmailField(unique=True,max_length=255, default=None)
address = models.CharField(max_length=70, default=None)
country = models.CharField(max_length=50, default=None)
state = models.CharField(max_length=50, default=None)
city = models.CharField(max_length=50, default=None)
zip = models.CharField(max_length=50, default=None)
birth_date = models.DateField(default=None)
license_no = models.IntegerField(default=None)
license_exp_date = models.DateField(default=None)
last_medical = models.DateField(default='', blank=True, null=True)
next_medical = models.DateField(default='', blank=True, null=True)
last_drug_test = models.DateField(default='', blank=True, null=True)
next_drug_test = models.DateField(default='', blank=True, null=True)
date_created = models.DateTimeField(auto_now_add=True)
status = models.IntegerField(choices=STATUS, default=1)
class DriversFiles(models.Model):
file = models.FileField(upload_to="media/", blank=True, null=True)
driver_files = models.ForeignKey('Drivers', on_delete=models.CASCADE, default=None, null=True)

Django_Tables2 Accessor / Related Fields

I have the following constellation of Tables, which are linked via FK's:
(omitted a few fields for better readability)
class ProductDetail(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
product_detail = models.CharField(max_length=100, primary_key=True, verbose_name='Product Detail Name')
materialcode = models.CharField(max_length=20, blank=False, null=False, verbose_name='Material-Code')
billing_model = models.ForeignKey(BillingModel, on_delete=models.CASCADE)
....
--------------
class MinimumRevenue(models.Model):
operator = models.ForeignKey(Operator, on_delete=models.CASCADE)
billing_model = models.ForeignKey(BillingModel, on_delete=models.CASCADE)
minimum_revenue = models.DecimalField(decimal_places=2, max_digits=20, verbose_name='Minimum Revenue')
currency = models.ForeignKey(Currency, on_delete=models.CASCADE)
product_detail = models.ForeignKey(ProductDetail, on_delete=models.CASCADE, verbose_name='Product Detail')
event_type_assignment = models.CharField(max_length=100, verbose_name='Event Type Assignment')
start_date = models.DateField(blank=False, null=False, verbose_name='Start Date', default=get_first_of_month)
end_date = models.DateField(blank=False, null=False, verbose_name='End Date')
....
And a Table (Django_Tables2) which points to the MinimumRevenue Model (which works as designed), now I would like to also show some more related fields in my Table:
class MinimumRevenueTable(tables.Table):
edit = tables.LinkColumn('non_voice:minimum_revenue_update', orderable=False, text='Edit', args=[A('pk')])
invoice_text = tables.TemplateColumn(
'<data-toggle="tooltip" title="{{record.context}}">{{record.invoice_text|truncatewords:2}}')
start_date = tables.DateColumn(format='Y-m-d')
end_date = tables.DateColumn(format='Y-m-d')
foreigncolumn = tables.Column(accessor='productdetail.materialcode')
class Meta:
model = MinimumRevenue
template_name = "django_tables2/bootstrap4.html"
fields = ('operator', 'billing_model', 'minimum_revenue', 'product', 'product_detail', 'event_type_assignment',
'start_date', 'end_date', 'invoice_text', 'currency', 'foreigncolumn')
attrs = {'class': 'table table-hover', }
The foreigncolumn column is never filled, just showing '-', I also tried it with other columns of ProductDetail, but never get any result, would really appreciate any solutions!

Django ManyToManyField inline list values

I have two Django models related by a ManyToManyField relationship. Everything works fine except for the inline add dropdown which lists ugly automatically created object names instead of allowing me to format it. How can I specify that?
Models:
class Job(models.Model):
type = models.CharField(max_length=32, choices=JobChoices)
guid = models.CharField(max_length=32)
title = models.CharField(max_length=256)
started_time = models.DateTimeField()
ended_time = models.DateTimeField(blank=True, null=True)
enabled = models.BooleanField(default=False)
running = models.BooleanField(default=False)
working_job_status = models.CharField(max_length=32, choices=StatusCoices)
working_job_length = models.IntegerField(blank=True, null=True)
working_job_progress = models.IntegerField(blank=True, null=True)
working_job_eta_sec = models.IntegerField(blank=True, null=True)
RepeatUnit = (
('s', 'Second'),
('m', 'Minute'),
('h', 'Hour'),
('d', 'Day'),
('W', 'Week'),
('M', 'Month'),
('Y', 'Year'),
)
class Schedule(models.Model):
title = models.CharField(max_length=128)
job = models.ManyToManyField(Job, blank=True, null=True)
start_time = models.DateTimeField(null=False)
end_time = models.DateTimeField(blank=True, null=True)
repeat_unit = models.CharField(blank=True, null=True, max_length=1, choices=RepeatUnit)
repeat_every = models.IntegerField(blank=True, null=True)
repeat_max_count = models.IntegerField(blank=True, null=True)
def __unicode__(self):
return f'{self.title}'
Admin:
class ScheduleAdmin(admin.ModelAdmin):
list_display = ['id', 'title', 'start_time', 'end_time', 'repeat_unit', 'repeat_every', 'repeat_max_count']
class ScheduleInline(admin.TabularInline):
model = Schedule.job.through
min_num = 0
extra = 0
# fields = ('title', )
verbose_name = "Schedule"
verbose_name_plural = "Schedules"
class JobAdmin(admin.ModelAdmin):
list_display = ['id', 'type', 'guid', 'title', 'started_time', 'ended_time', 'enabled', 'running', 'progress']
inlines = [ScheduleInline,]
admin.site.register(Schedule, ScheduleAdmin)
admin.site.register(Job, JobAdmin)
And, when I click on the inlines drop-down menu I get:
changing from __unicode__(self) to __str__(self) did the trick

Django rest framework - cant serialize query set

I try to serialize query set
def do(self):
reservations = Reservation.objects.all()
serializer = ReservationSerializer(data=reservations, many=True)
if serializer.is_valid():
encoded_data = json.dumps(serializer.data)
r = requests.post('http://httpbin.org/post', headers={'Content-Type': 'application/json'}, data=encoded_data)
print(r.text)
else:
print(serializer.errors)
And I always get error of
{u'non_field_errors': [u'Expected a list of items but got type "QuerySet".']}
I tried to use values() on query set, and then convert to list, but this way I get objects without nested models
model
class Reservation(models.Model):
start = models.DateField(verbose_name='Заезд', auto_now=False, auto_now_add=False, blank=False)
end = models.DateField(verbose_name='Выезд', auto_now=False, auto_now_add=False, blank=False)
check_in_time = models.TimeField(verbose_name='Время заезда', blank=False)
check_out_time = models.TimeField(verbose_name='Время выезда', blank=False)
has_refund = models.BooleanField(verbose_name='Возвратная бронь', default=True)
payed = models.BooleanField(verbose_name='Оплачено', default=False)
reserved_days = models.ManyToManyField(Day, blank=False)
additional_services = models.ManyToManyField(AdditionalService)
guest_name = models.CharField(verbose_name='Имя гостя', max_length=200, blank=True)
reservation_number = models.CharField(verbose_name='Номер брони', max_length=200, blank=True)
class AdditionalService(models.Model):
payment_date = models.CharField(verbose_name='Дата оплаты', max_length=200, blank=True)
payment_type = models.CharField(verbose_name='Форма оплаты', max_length=200, blank=False)
service = models.CharField(verbose_name='Услуга', max_length=200, blank=False)
quantity = models.IntegerField(blank=False)
price = models.FloatField(blank=False)
class Day(models.Model):
date = models.DateField(auto_now=False, auto_now_add=False)
price = models.FloatField()
payment_method = models.CharField(max_length = 200, blank=True)
payment_date = models.CharField(max_length=200, blank=True)
room = models.ForeignKey(Room, null=True, blank=True, verbose_name='Номер', on_delete=models.CASCADE)
class Room(models.Model):
name = models.CharField(max_length = 200, null=True)
id = models.AutoField(primary_key=True)
room_id = models.CharField(max_length = 200, null=False)
def __unicode__(self):
return self.name
serializers
class ReservationSerializer(serializers.ModelSerializer):
reserved_days = DaySerializer(many=True)
additional_services = AdditionalServicesSerializer(many=True)
class Meta:
model = Reservation
fields = [
'start',
'end',
'check_in_time',
'check_out_time',
'reserved_days',
'additional_services',
'has_refund',
'payed',
'guest_name',
'reservation_number',
]
class DaySerializer(serializers.ModelSerializer):
room = RoomSerializer()
class Meta:
model = Day
fields = [
'date',
'price',
'payment_method',
'payment_date',
'room',
]
class AdditionalServicesSerializer(serializers.ModelSerializer):
class Meta:
model = AdditionalService
fields = [
'payment_date',
'payment_type',
'service',
'quantity',
'price',
]
class RoomSerializer(serializers.ModelSerializer):
class Meta:
model = Room
fields = [
'room_id',
]
For serialization you don't need to use data keyword, just pass queryset as first positional argument:
serializer = ReservationSerializer(reservations, many=True)
return serializer.data

Django admin admin_order_field with other table

How to sort by custom field in Django admin.
My database's tables are without any ForeignKey,
django framework design by related ship.
This model define:
class UserBaseInfo(BaseModel):
STATUS = [(0, 'not pass'), (1, 'pass')]
SEX = [(0, 'unset'), (1, 'male'), (2, 'female')]
parent_id = models.IntegerField(max_length=11, default=0)
level_id = models.IntegerField(max_length=11, default=1)
phone = models.BigIntegerField(max_length=15, null=True, blank=True, default=None)
nickname = models.CharField(max_length=100)
sex = models.IntegerField(null=False, blank=False, default=1, choices=SEX)
country = models.CharField(max_length=100, null=True, blank=True)
province = models.CharField(max_length=100, null=True, blank=True)
city = models.CharField(max_length=100, null=True, blank=True)
headimgurl = models.CharField(max_length=255, null=True, blank=True)
status = models.IntegerField(max_length=3, default=0)
updated_time = models.BigIntegerField(max_length=18, null=True, blank=True)
class Meta:
db_table = 'user_base_info'
ordering = ('-created_time', '-updated_time')
def save(self, force_insert=False, force_update=False, using=None,
update_fields=None):
initial = False
if not self.id:
initial = True
super(UserBaseInfo, self).save(force_insert=force_insert, force_update=force_update, using=using,
update_fields=update_fields)
if initial:
Wallet(user_id=self.id, money=1000).save()
class Wallet(models.Model):
user_id = models.BigIntegerField(max_length=18, primary_key=True, null=False, blank=False, verbose_name=_('UserId'))
money = models.FloatField(null=False, blank=False)
class Meta:
db_table = 'wallet'
This admin
class UserBaseInfoAdmin(CSVAdmin):
list_display = ('nickname', 'avatar', 'level_id', 'parent', 'income', 'sex', 'country', 'province', 'city')
list_filter = ('nickname', 'level_id', 'sex', ('created_time', DateFieldListFilter), ('updated_time', DateFieldListFilter))
search_fields = ('nickname', 'level_id', 'sex', 'created_time', 'updated_time')
list_display_links = ('level_id',)
readonly_fields = ('nickname', 'level_id', 'sex', 'country', 'province', 'city', 'headimgurl',
'language', 'openid', 'privilege', 'created_time', 'updated_time')
list_per_page = 20
list_max_show_all = 20
def avatar(self, data):
return format_html('<img src="%s" height="50px" style="border-radius:50px"/>' % data.headimgurl)
def parent(self, data):
user = UserBaseInfo.objects.filter(pk=data.parent_id).first()
return user.nickname if user else ''
parent.allow_tags = True
parent.admin_order_field = 'parent_id'
def income(self, data):
wallet = Wallet.objects.filter(user_id=data.id).first()
if wallet:
return wallet.money / 100
income.admin_order_field = 'wallet__money'
I want to order by wallet's money, but I don't how to do next;