How to query translatable fields with graphene - django

Assuming a model that has translated fields like below, how can we query these with django-graphene?
from parler.models import TranslatableModel, TranslatedFields
class Article(TranslatableModel):
#regular fields
publishing_date = models.DateTimeField(_('publishing date'),
default=now)
# translated fields
translations = TranslatedFields(
title=models.CharField(_('title'), max_length=234),
slug=models.SlugField(
verbose_name=_('slug'),
max_length=255,
db_index=True,
blank=True,
),
meta_title=models.CharField(
max_length=255, verbose_name=_('meta title'),
blank=True, default=''),
meta_description=models.TextField(
verbose_name=_('meta description'), blank=True, default=''),
meta_keywords=models.TextField(
verbose_name=_('meta keywords'), blank=True, default=''),
)
For registering "unknown" fields I do something like:
#convert_django_field.register(GeopositionField)
def convert_geofield_to_string(field, registry=None):
return graphene.String(description=field.help_text, required=not field.null)
... but this won't work here. Any ideas?

Related

mptt not linking children and parent - Django

I'm having an issue that I seriously can't wrap my head around.
I am using Django MPTT models and evrerything seems to be working fine (i.e. I can run the migrations and insert data in the database), but for some reason the
TreeForeignKey
table and the
TreeManyToManyField
table are not linking in the database.
Here are the models in question...
from mptt.models import MPTTModel, TreeForeignKey, TreeManyToManyField
class Category(MPTTModel):
name = models.CharField(
max_length=100,
verbose_name=_('category name'),
help_text=_('format: required, max=100'),
)
slug = models.SlugField(
max_length=150,
verbose_name=_('category safe URL'),
help_text=_('format: required, letters, numbers, underscore or hyphons'),
)
is_active = models.BooleanField(default=True)
parent = TreeForeignKey(
'self',
on_delete=models.PROTECT,
related_name='children',
null=True,
blank=True,
)
class MPTTMeta:
order_insertion_by = ['name']
class Meta:
verbose_name=_('product category')
verbose_name_plural=_('product categories')
def __str__(self):
return self.name
class Product(models.Model):
web_id = models.CharField(
unique=True,
max_length=50,
verbose_name=_('product website ID'),
)
slug = models.SlugField(
max_length=255,
verbose_name=_('product safe URL'),
help_text=_('format: required, letters, numbers, underscore or hyphons'),
)
name = models.CharField(max_length=150)
description = models.TextField(help_text='Required')
category = TreeManyToManyField(Category)
is_active = models.BooleanField(
default=False,
verbose_name=_('product visibility'),
)
created_at = models.DateTimeField(
editable=False,
auto_now_add=True,
help_text=_('format: Y-m-d H:M:S'),
)
updated_at = models.DateTimeField(auto_now=True, help_text=_('format: Y-m-d H:M:S'))
def __str__(self):
return self.name
I'm following the documentation verbatum, and really I have no idea why this is not working...
If anyone has any idea please let me know

Django ModelForm - Using ForeignKey for Choices

I'm attempting to build out a rather large "Patient Onboarding" form using ModelForms.
I'm having trouble getting the choices within the foreign keys to appear in the admin area or to the rendered form without manually adding them to the Postgres database.
There has got to be a more efficient way to be doing this...thanks in advance!
#models.py
from django.db import models
from django.forms import ModelForm
from django import forms
class Patient(models.Model):
first_name = models.CharField(max_length=30, verbose_name='First Name', blank=False)
middle_name = models.CharField(max_length=30, verbose_name='Middle Name', blank=False)
last_name = models.CharField(max_length=30, verbose_name='Last Name', blank=False)
gender = models.ForeignKey('GenderChoices', on_delete=models.CASCADE, verbose_name='Gender', blank=False)
date_of_birth = models.DateField(verbose_name='Date of Birth', blank=False)
medications = models.ForeignKey('MedicationsYesNo', on_delete=models.CASCADE, verbose_name='Do you currently take any medications?', blank=False)
class MedicationsYesNo(models.Model):
medications_yes_no = models.CharField(
max_length=100,
choices = [
('Yes', 'Yes'),
('No', 'No')
]
)
def __str__(self):
return self.medications_yes_no
class OnboardingForm(ModelForm):
class Meta:
model = Patient
fields = '__all__'

How to allow blank field on OneToOne serializer field for Django REST Framework API?

When POSTing to my API endpoint I get a field is required error on a OneToOne field, but I create the OneToOne Field in the save() method of the model I'm POSTing.
I've tried setting default=None, null=True, and blank=True
Device Model
class Device(models.Model):
name = models.CharField(max_length=50)
created = models.DateTimeField(auto_now_add=True, editable=False)
last_updated = models.DateTimeField(auto_now=True, editable=False)
brand = models.TextField(max_length=50)
year_purchased = models.IntegerField()
serial_number = models.TextField(max_length=100)
info = models.TextField(max_length=100)
qrcode = models.ImageField(upload_to='', blank=True, null=True)
def save(self, **kwargs):
super(Device, self).save(**kwargs)
if not self.qrcode:
self.generate_qrcode()
if not self.checkouts.exists():
checkout = Checkout(item=self)
checkout.save()
Checkout Model
class Checkout(models.Model):
status_choices = (...)
# Fields
slug = extension_fields.AutoSlugField(populate_from='item', blank=True)
created = models.DateTimeField(auto_now_add=True, editable=False)
last_updated = models.DateTimeField(auto_now=True, editable=False)
due_back = models.DateField(null=True, blank=True)
checked_out = models.DateTimeField(blank=True, null=True)
status = models.CharField(max_length=2, choices=status_choices, default=in_stock)
# Relationship Fields
user = models.OneToOneField(
DeviceUser,
on_delete=models.CASCADE,
related_name="checkouts",
blank=True,
null=True,
default=None,
)
item = models.OneToOneField(
Device,
on_delete=models.CASCADE,
related_name="checkouts",
primary_key=True,
blank=True,
default=None,
)
Device Serializer
class DeviceSerializer(serializers.ModelSerializer):
class Meta:
model = models.Device
fields = (
'pk',
'name',
'created',
'last_updated',
'brand',
'year_purchased',
'serial_number',
'info',
'checkouts',
)
When POSTing http POST http://localhost:8000/main/api/device/ brand=test2 info=123213123 name=test2 serial_number=12321321 year_purchased=12 'Authorization: Token .....'
I expect to get a confirmation that a device was created, instead I get
"checkouts": [ "This field is required." ]
Specify checkouts field to your DeviceSerializer serializer as,
checkouts = serializers.DateTimeField(default=None, source='checkouts.checked_out', read_only=True)
# code sample
class DeviceSerializer(serializers.ModelSerializer):
checkouts = serializers.DateTimeField(default=None, source='checkouts.checked_out', read_only=True)
class Meta:
model = models.Device
fields = (
'pk',
'name',
'created',
'last_updated',
'brand',
'year_purchased',
'serial_number',
'info',
'checkouts',
)

Django-Tables2 LinkColumn link goes to wrong item

I have a Django project and I am having issues with the hyperlink (LinkColumn from Django-tables2) going to the incorrect entry and I cannot figure out why it is occurring or how to fix it.
Very specifically, I can go to the admin view and create a publication. When it comes to setting the author (a.k.a. pi) or sample, there is a drop down menu for foreign key fields (sample/pi) that shows all existing entries from which I can choose one. When I choose a sample and pi then look at the table rendering, the hyperlink is there for the sample, pi, and the publication title. The publication title correctly takes me to the publication_detail page. The hyperlink for the sample will take me to a sample detail page, but it is not the same sample I selected from the admin page. I have the same issue for the author; it takes me to the detail view page of AN author, just not the one I selected from the admin page.
I use django-tables2 several times throughout the project and like how the tables are rendered, but cannot figure out how to address this problem. I have included some of my code (please note I included a bit of the PI and Sample model, but not all of it).
Any assistance is greatly appreciated.
models.py
class PI(models.Model): #this is a smattering of the PI model
l_name = models.CharField('L Name', blank=False, max_length=100, default='')
f_name = models.CharField('F Name', blank=False, max_length=100, default='')
m_name = models.CharField('MI', null=True, blank=True, max_length=1, default='' )
phone = PhoneField(blank=True, default='')
email = models.EmailField('Email', blank=True, max_length=100, default='')
class Sample(models.Model): #this is a smattering of the Sample model
sample_name = models.CharField('Sample', max_length=16)
pi = models.ForeignKey(PI, on_delete=models.SET_NULL, null=True)
submitter = models.ForeignKey('Submitter', blank=True, on_delete=models.SET_NULL, null=True)
class Publication(models.Model):
sample = models.ForeignKey(Sample, on_delete=models.SET_NULL, null=True)
author = models.ForeignKey(PI, on_delete=models.SET_NULL, null=True)
title_p = models.CharField('Title', max_length=200, blank=False, default='')
volume = models.IntegerField('Volume', blank=True, null=True)
number = models.IntegerField('Number', blank=True, null=True)
pages = models.CharField('Pages', default='', max_length=20, blank=True)
year = models.IntegerField('Year', blank=True, null=True)
doi = models.CharField('DOI', default='', max_length=30, blank=False)
journal = models.CharField('Journal', default='', max_length=100, blank=False)
abstract = models.CharField('Abstract', default='', max_length=1000, blank=False)
issn = models.CharField('ISSN', default='', max_length=10, blank=False)
url = models.CharField('URL', default='', max_length=100, blank=False)
eprint = models.CharField('Eprint', default='', max_length=100, blank=False)
class Meta:
ordering = ('sample', 'author', 'title_p', 'journal', 'volume', 'number', 'pages', 'year', 'doi', 'abstract', 'issn', 'url', 'eprint')
def get_absolute_url(self):
return reverse('publication-detail', args=[str(self.id)])
def __str__(self):
return f'{self.sample}, {self.author}, {self.title_p}, {self.volume}, {self.number}, {self.pages}, {self.year}, {self.doi}, {self.journal}, {self.abstract}, {self.issn}, {self.url}, {self.eprint}'
tables.py
class PublicationTable(tables.Table):
sample = tables.LinkColumn('sample-detail', args=[A('pk')])
author = tables.LinkColumn('pi-detail', args=[A('pk')])
title_p = tables.LinkColumn('publication-detail', args=[A('pk')])
class Meta:
model = Publication
fields = ( 'sample', 'author', 'title_p', 'journal', 'year', )
exclude = ( 'volume', 'number', 'pages', 'doi', 'abstract', 'issn', 'url', 'eprint', )
list_display = ('sample', 'author', 'title_p', 'year', 'journal', )
views.py
class PublicationListView(generic.ListView):
model = Publication
paginate_by = 100
#login_required
def publication_view(request, pk):
publication = Publication.objects.get(pk = pk)
table = PublicationTable(Publication.objects.filter(publication=pk))
RequestConfig(request).configure(table)
return render(request, 'samples/publication_detail.html', {'publication': publication, 'publication-detail': table})
#login_required
def publication_table(request):
table = PublicationTable(Publication.objects.all())
RequestConfig(request).configure(table)
return render(request, 'samples/publication_list.html', {'publication_table': table})
class PublicationDetailView(generic.DetailView):
model = Publication
urls.py
urlpatterns = [
path('', views.index, name='index'),
path('samples/', views.sam, name='sam'),
path('sample/<int:pk>', views.SampleDetailView.as_view(), name='sample-detail'),
path('pi/', views.pi_table, name='pi_table'),
path('pi/<int:pk>', views.pi_view, name='pi-detail'),
path('publication/', views.publication_table, name='publication_table'),
path('publication/<int:pk>', views.PublicationDetailView.as_view(), name='publication-detail'),
]
A bit of code from samples/templates/samples/publication_list.py
{% render_table publication_table %}
Well, passing pk through accessor means, it will pass the primary key of Publication Model objects for pi-details, sample-details, and so on. So you need to change it so that you pass the respective primary keys throught the accessor like this:
class PublicationTable(tables.Table):
sample = tables.LinkColumn('sample-detail', args=[A('sample_id')])
author = tables.LinkColumn('pi-detail', args=[A('author_id')])
title_p = tables.LinkColumn('publication-detail', args=[A('pk')])

django admin and inlines: many-to-many with 'through' model - performance issue

I have a problem with a m2m field that use an intermediated model ('through') with the admin and inlines. here's the code:
# MODELS
class Engagement(models.Model):
parent_engagement = models.ForeignKey('self', blank=True, null=True, related_name='child_engagements')
title = models.CharField('Engagement title', max_length=200)
...
# client
client = models.ForeignKey(Client, related_name='engagements')
primary_point_of_contact = models.ForeignKey(
ClientContact, null=True, blank=True,
related_name='engagements_for_which_point_of_contact'
)
additional_point_of_contacts = models.ManyToManyField(
ClientContact,
through='AdditionalPointOfContact'
)
.... # other fields
class ClientContact(models.Model):
first_name = models.CharField(max_length=200, blank=True)
last_name = models.CharField(max_length=200, blank=True)
jobtitle = models.CharField(max_length=200, blank=True)
company = models.ForeignKey(Client, null=True, blank=True)
class AdditionalPointOfContact(models.Model):
engagement = models.ForeignKey("Engagement", related_name='additional_points_of_contact')
client_contact = models.ForeignKey("ClientContact")
description = models.CharField(max_length=500, blank=True)
def __unicode__(self):
return self.client_contact.__unicode__()
# ADMIN
class EngagementAdmin(ChaosDefaultAdmin):
....
inlines = [
ScopeServiceElementAdmin,
AdditionalPointOfContactInlineAdmin
]
list_display = (...
class AdditionalPointOfContactInlineAdmin(admin.TabularInline):
model = AdditionalPointOfContact
fieldsets = [
('', {
'fields': (('client_contact',),
('description',),)
}),
]
extra = 0
min_num = 0
according to the django-debug-toolbar, the sql tab says 8382 queries, while commenting out AdditionalPointOfContactInlineAdmin it reduces to 10 queries, so there's something wrong there.
I might override the get_queryset method of AdditionalPointOfContactInlineAdmin, but I don't know exactly how and why. Any suggestion?
Try override EngagementAdmin.get_queryset():
class EngagementAdmin(ChaosDefaultAdmin):
def get_queryset(self, request):
qs = super(EngagementAdmin, self).get_queryset(request)
return qs.prefetch_related('additional_points_of_contact')
# or
# return qs.prefetch_related('additional_points_of_contact__client_contact')