Django createview using primary key - django

I have a model like this:
class Appointment(models.Model):
user = models.ForeignKey(User)
engineer = models.ForeignKey(Engineer)
first_name = models.CharField(max_length=100)
middle_name = models.CharField(max_length=100, blank=True)
last_name = models.CharField(max_length=100)
age = models.IntegerField()
def __unicode__(self):
return self.first_name
I have created a form using this model and I want to save it. Here I want the 'engineer' field to to be as the primary key is passed in the url.. like
engineer = Engineer.objects.get(pk=pk)
How can I do this. Or I should create a normal form and get its value via get method and assign to the field??

Since this is a CreateView, you should build on the example in the documentation and add it in form_valid:
def form_valid(self, form):
form.instance.engineer = Engineer.objects.get(pk=self.kwargs['pk'])
return super(AppointmentCreate, self).form_valid(form)

Related

Django Advice - model_to_dict - User returning ID instead of username

I'm calling the model_to_dict function and it is working,
but i want to be able to modify the results before returning.
The Author area is currently returning an id number and I want it to return the Username instead.
Does anybody know how to make that happen?
.model
class Comment(models.Model):
poopfact = models.ForeignKey(PoopFact, related_name="comments", on_delete=models.CASCADE)
author = models.ForeignKey(User, on_delete=models.CASCADE)
comment = models.TextField(unique=True, blank=True, null=True)
datetime = models.DateTimeField(auto_now_add=True)
likes = models.ManyToManyField(User, related_name="comment_likes")
.views
def comment(request, poopfact_id):
...
new_entry = Comment()
...
data = model_to_dict(new_entry)
return JsonResponse(data, safe=False)
Add this method to User model. By default user object represent itself as ID. Just replace it with username field in model (note: I am considering the 'username' is your User model field)
def __str__(self):
return self.username

Two step object creation in Django Admin

I'm trying to change the implementation of an EAV model using a JSONField to store all the attributes defined by an attribute_set.
I already figured out how to build a form to edit the single attributes of the JSON, but I'm currently stuck at implementing the creation of a new object. I think I have to split object creation in two steps, because I need to know the attribute_set to generate the correct form, but I don't know if there's a way to hook in the create action, or any other way to achieve what I need.
My models look like this:
class EavAttribute(models.Model):
entity_type = models.CharField(max_length=25, choices=entity_types)
code = models.CharField(max_length=30)
name = models.CharField(max_length=50)
data_type = models.CharField(max_length=30, choices=data_types)
class AttributeSet(models.Model):
name = models.CharField(max_length=25)
attributes = models.ManyToManyField('EavAttribute')
class EntityAbstract(models.Model):
attribute_set = models.ForeignKey(
'AttributeSet',
blank=False,
null=False,
unique=False,
)
class Meta:
abstract = True
class Event(EntityAbstract):
entity_type = models.CharField(max_length=20, null=False, choices=entity_types, default=DEFAULT_ENTITY_TYPE)
code = models.CharField(max_length=25, null=True, blank=True, db_index=True)
year = models.IntegerField(db_index=True)
begin_date = models.DateField()
end_date = models.DateField()
data = JSONField()
How can I choose the AttributeSet first and then go to another form that I would populate with the attributes in the chosen attribute set?
I ended up using get_fields() and response_add() methods, like so:
def get_fields(self, request, obj=None):
if obj is None:
return ['attribute_set']
else:
return [attr.name for attr in obj._meta.get_fields() if not attr.auto_created and attr.name != 'id']
def get_readonly_fields(self, request, obj=None):
readonly_fields = ['entity_type', 'code', 'state']
if obj is not None:
readonly_fields.append('attribute_set')
return readonly_fields
def response_add(self, request, obj, post_url_continue=None):
url = '/admin/risks/event/{}/change/'.format(obj.id)
return redirect(url)
The downside of this approach is that object is saved in the database and then opened for edit, so basically the database is hit twice and all attributes have to be nullable, except for attribute_set.
I would be happy to receive ideas for better implementations.

Django Customize many to many query

I have extended Django's default User class by adding a ManyToManyField to another table called Algorithm. The new User class is:
class User(AbstractUser):
name = CharField(_("Name of User"), blank=True, max_length=255)
algorithms = ManyToManyField(Algorithm, blank=True, default=None, related_name="users")
def get_absolute_url(self):
return reverse("users:detail", kwargs={"username": self.username})
I want to specify if the user is_superuser or is_staff then User.algorithms.all() will get all algorithms. Otherwise, get only the records in the pivot table User_user_models. How can this be achieved? I tried to add a property method that check if superuser/staff then return all otherwise return super but it didn't work.
P.S: during creating/editing the user, if user is set to superuser or staff, then there is no need to choose algorithms.
I would just overwrite the save() method:
class User(AbstractUser):
name = CharField(_("Name of User"), blank=True, max_length=255)
algorithms = ManyToManyField(Algorithm, blank=True, default=None, related_name="users")
def get_absolute_url(self):
return reverse("users:detail", kwargs={"username": self.username})
def save(self, **kwargs):
if self.is_superuser or self.is_staff:
self.algorithms = Algorithm.objects.all()
else:
# Get your users from your pivot table
super().save()

Saving the Users Profile to the Model

When the form saves I want to save the object with a reference to the user's Profile page. So each profile can list every offer made by the user,
see Class based views query: get objects referenced by another model
ofertoj_oferto.profile_id may not be NULL
My model of "Oferto" contains a ForeignKey to the User's Profile. Right now I don't have an idea how i can tell the system "Get the logged in User's Profile and save this Ofeto with that ID"
Maybe there is some way where I lookup the profile associated with the user and don't need both user and profile on the Oferto model.
But I will still need to a list of every oferto made by the user on there profile
profiles.models
class Profile(BaseInfo):
bio = models.TextField(max_length=15000000)
user = models.ForeignKey(User)
views.py
class OfertoCreateView(LoginRequiredMixin, Turtle_CreateView):
model = Oferto
action = "created"
form_class = OfertoCreateForm
forms.py
class OfertoCreateForm(Turtle_Form):
class Meta:
model = Oferto
fields = ("name",
"description",
"tags",
"time",
"requirements",
"location",
"image",)
models.py
class Oferto(models.Model):
user = models.ForeignKey(User)
profile = models.ForeignKey(Profile)
name = models.CharField(max_length=150)
description = models.TextField(max_length=3000)
time = models.DecimalField(max_digits=10000000, decimal_places=2, null=True)
stelo = models.DecimalField(max_digits=10000000, decimal_places=2, null=True)
location = models.TextField(max_length=3000)
slug = AutoSlugField(('slug'), max_length=128, unique=True, populate_from=('name',))
tags = tagging.fields.TagField()
image = models.ImageField(upload_to='Ofertoj', blank=True, null=True)
requirements = models.TextField(max_length=550000, blank=True, null=True)
def get_absolute_url(self):
return reverse('oferto_detail', kwargs={'slug': self.slug})
def __unicode__(self):
return self.name
def get_tags(self):
return Tag.objects.get_for_object(self)
In your view/form/model save area: calling request.user returns a User object you can send to a model's ForeignKey field

Django 1.5 ModelForm like admin in view with images and foreign key

I have the following models:
class Quiver(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
is_default = models.BooleanField(default=False)
type = models.CharField(max_length=1, choices=QUIVER_TYPES)
category = models.CharField(max_length=255, choices=QUIVER_CATEGORIES)
def __unicode__(self):
return u'[%s] %s %s quiver' % (
self.user.username,
self.get_type_display(),
self.get_category_display())
class Image(models.Model):
photo = models.ImageField(upload_to=get_upload_file_path)
is_cover = models.BooleanField(default=False)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey()
def save(self, *args, **kwargs):
try:
this = Image.objects.get(pk=self.pk)
if this.photo != self.photo:
this.photo.delete(save=False)
except Image.DoesNotExist:
pass
super(Image, self).save(*args, **kwargs)
class Surfboard(models.Model):
quiver = models.ForeignKey(Quiver)
brand = models.CharField(max_length=255)
model = models.CharField(max_length=255)
length = models.CharField(max_length=255)
width = models.CharField(max_length=255, blank=True)
thickness = models.CharField(max_length=255, blank=True)
volume = models.CharField(max_length=255, blank=True)
images = generic.GenericRelation(Image)
def __unicode__(self):
return u'%s %s %s' % (self.length, self.brand, self.model)
def get_cover_image(self):
"Returns the cover image from the images uploaded or a default one"
for image in self.images.all():
if image.is_cover:
return image
return None
I'd like to be able to have the same form I have in the admin in my frontend view /surfboard/add:
As a new Django fan and user, I started to create the form from scratch. Not being able to do what I want with including the foreign key "quiver" as a dropdown list, I found in the doc the ModelForm, and decided to use it, so here what I got:
class SurfboardForm(ModelForm):
class Meta:
model = Surfboard
In my view, it looks like this and it's already a good start:
So now, I wanted to have a way to add pictures at the same time, and they are linked to a surfboard via a Generic Relation. Here I don't find the way to do a implementation like in the admin, and get frustrated. Any tips to do so?
Thanks!
What you seek is called an inline formset - see the docs for more.
It's also handy that you can render a formset quickly with {{ formset.as_p }}, but you'll need to write some JavaScript (or use the JavaScript that's used in the Django admin) to handle adding and removing forms.