I am running django 1.8, I am trying to save the current logged in user in the created by and modified by fields in my database. I have tried many different combination of getting this to work, but I am not running into any luck. I have to code working with hard coding in a user id like so:
#python_2_unicode_compatible # only if you need to support Python 2
class Project(models.Model):
name = models.CharField(max_length=50, verbose_name="Name")
jobNumber = models.CharField(max_length=8)
shopOut = models.DateTimeField(null=True)
shopIn = models.DateTimeField(null=True)
completion = models.DateTimeField(null=True)
installation_date = models.DateTimeField(null=True)
contractor = models.ForeignKey(Contractor, on_delete=models.CASCADE, default=101)
created_by = models.ForeignKey(User, related_name='Project_created_by')
created_date = models.DateTimeField(auto_now_add=True)
modified_by = models.ForeignKey(User, related_name='Project_modified_by')
modified_date = models.DateTimeField(auto_now=True)
assigned_to = models.ForeignKey(User, related_name='Project_assigned_to', default=1)
status = models.ForeignKey('Status', related_name='Project_status', default=1)
def __str__(self):
return self.name
def save(self, *args, **kwargs):
if not self.id:
self.created_by = User.objects.get(id=1)
#self.created_by = User.objects.get(id=kwargs['request'].user)
#self.created_by = User.objects.get(id=request.user)
self.modified_by = User.objects.get(id=1)
#self.modified_by = User.objects.get(id=kwargs['request'].user)
#self.modified_by = User.objects.get(id=request.user)
super(Project, self).save(*args, **kwargs)
year = datetime.datetime.now().year
self.jobNumber = '{}{:04d}'.format(year, self.id)
self.modified_by = User.objects.get(id=1)
#self.modified_by = User.objects.get(id=kwargs['request'].user)
#self.modified_by = User.objects.get(id=request.user)
super(Project, self).save(*args, **kwargs)
If I try any of the code commented out:
self.created_by = User.objects.get(id=kwargs['request'].user)
or
self.created_by = User.objects.get(id=request.user)
I get the following error:
KeyError at /admin/project/project/add/
'request'
or
NameError at /admin/project/project/add/
global name 'request' is not defined
Once again my question is how do I save the current logged in user in my created_by and modified_by fields?
Any help would be greatly appreciated!
After searching a little more I found this post I followed most of their code, but here is mine:
This is my app folder structure:
myapp
project
admin.py # changed this
models.py # changed this
...
myapp
setting.py
url.py
...
my new admin.py
from django.contrib import admin
from . import models
class ProjectAdmin(admin.ModelAdmin):
fields = ('name', 'jobNumber', 'contractor', 'assigned_to', 'status')
def save_model(self, request, obj, form, change):
instance = form.save(commit=False)
if not hasattr(instance, 'created_by'):
instance.created_by = request.user
instance.modified_by = request.user
instance.save()
form.save_m2m()
return instance
admin.site.register(models.Project,ProjectAdmin)
models.py
import datetime
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
from django.contrib.auth.models import User
from contractor.models import Contractor
#python_2_unicode_compatible # only if you need to support Python 2
class Project(models.Model):
name = models.CharField(max_length=50, verbose_name="Name")
jobNumber = models.CharField(max_length=8)
shopOut = models.DateTimeField(null=True)
shopIn = models.DateTimeField(null=True)
completion = models.DateTimeField(null=True)
installation_date = models.DateTimeField(null=True)
contractor = models.ForeignKey(Contractor, on_delete=models.CASCADE, default=101)
created_by = models.ForeignKey(User, related_name='Project_created_by')
created_date = models.DateTimeField(auto_now_add=True)
modified_by = models.ForeignKey(User, related_name='Project_modified_by')
modified_date = models.DateTimeField(auto_now=True)
assigned_to = models.ForeignKey(User, related_name='Project_assigned_to', default=1)
status = models.ForeignKey('Status', related_name='Project_status', default=1)
def __str__(self):
return self.name
def save(self, *args, **kwargs):
if not self.id:
super(Project, self).save(*args, **kwargs)
year = datetime.datetime.now().year
self.jobNumber = '{}{:04d}'.format(year, self.id)
super(Project, self).save(*args, **kwargs)
I guess the trick is catching the request in the admin.py file. Thanks solarissmoke for your input!
you can use django-currentuser package.
for example:
from django_currentuser.middleware import get_current_authenticated_user
class Project(models.Model):
....
self.modifier = get_current_authenticated_user()
if not self.id:
self.creator = get_current_authenticated_user()
....
Related
I'm looking to connect two SQLite tables together (oh dear).
I found this solution : How to use django models with foreign keys in different DBs? , I adapted it to my models and my code (I think). I have no bad answers from django. However, I would like to modify the entry with the admin view of django, and when I try to add the entry with the foreign key of another database, I get this answer:
Exception Type: OperationalError at /admin/users/character/add/
Exception Value: no such table: books
How to adapt to fix it?
models database default
from django.db import models
from users.related import SpanningForeignKey
from books.models import Books
class Character(models.Model):
last_name = models.fields.CharField(max_length=100)
first_name = models.fields.CharField(max_length=100)
book = SpanningForeignKey('books.Books', null=True, on_delete=models.SET_NULL)
def __str__(self):
return f'{self.first_name} {self.last_name}'
models external database
from django.db import models
# Create your models here.
class Books(models.Model):
title = models.TextField()
sort = models.TextField(blank=True, null=True)
timestamp = models.TextField(blank=True, null=True) # This field type is a guess.
pubdate = models.TextField(blank=True, null=True) # This field type is a guess.
series_index = models.FloatField()
author_sort = models.TextField(blank=True, null=True)
isbn = models.TextField(blank=True, null=True)
lccn = models.TextField(blank=True, null=True)
path = models.TextField()
flags = models.IntegerField()
uuid = models.TextField(blank=True, null=True)
has_cover = models.BooleanField(blank=True, null=True)
last_modified = models.TextField() # This field type is a guess.
class Meta:
managed = False
db_table = 'books'
app_label = 'books'
class Languages(models.Model):
lang_code = models.TextField()
class Meta:
managed = False
db_table = 'languages'
app_label = 'books'
class BooksLanguagesLink(models.Model):
book = models.ForeignKey(Books, null=True, on_delete=models.SET_NULL, db_column='book')
lang_code = models.ForeignKey(Languages, null=True, on_delete=models.SET_NULL, db_column='lang_code')
item_order = models.IntegerField()
class Meta:
managed = False
db_table = 'books_languages_link'
app_label = 'books'
admin books
from django.contrib import admin
from books.models import Books, Languages
class BooksModelAdmin(admin.ModelAdmin):
using = 'calibre_db'
def save_model(self, request, obj, form, change):
obj.save(using=self.using)
def delete_model(self, request, obj):
obj.delete(using=self.using)
def get_queryset(self, request):
return super().get_queryset(request).using(self.using)
def formfield_for_foreignkey(self, db_field, request, **kwargs):
return super().formfield_for_foreignkey(db_field, request, using=self.using, **kwargs)
def formfield_for_manytomany(self, db_field, request, **kwargs):
return super().formfield_for_manytomany(db_field, request, using=self.using, **kwargs)
# Register your models here.
admin.site.register(Books, BooksModelAdmin)
When i'm trying to add a Post through django admin i get an error that the Post im trying to add needs to have a value for field id. Do you have any idea why?
now = datetime.now()
class Category(models.Model):
name = models.CharField(max_length=200)
slug = models.SlugField(unique=True)
class Meta:
verbose_name_plural = "categories"
def __str__(self):
return self.name
class Post(models.Model):
title = models.CharField(max_length=100)
excerpt = models.CharField(max_length=200)
main_image = models.ImageField()
author = models.ForeignKey(users.models.CustomUser, on_delete=models.CASCADE, related_name='blog_posts', null=True)
content = models.TextField(null=True)
created_at = models.DateTimeField(editable=False)
updated_at = models.DateTimeField(editable=False)
category = models.ManyToManyField(Category, related_name='post_category')
class Meta:
ordering = ['-created_at']
def save(self, *args, **kwargs):
if not self.id:
self.created_at = now
self.updated_at = now
def __str__(self):
return self.title
You need to make a super().save(*args, **kwargs) call. Furthermore using a constant will not work: this will assign the time when you started the server, not the current time, so:
from django.utils.timezone import now
class Post(models.Model):
# …
def save(self, *args, **kwargs):
if not self.id:
self.created_at = now()
self.updated_at = now()
super().save(*args, **kwargs)
You furthermore do not need to specify logic to update the created_at and updated_at field, you can work with auto_now_add=True [Django-doc] and auto_now=True [Django-doc]:
class Post(models.Model):
# …
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
# …
class Meta:
ordering = ['-created_at']
# no save override
def __str__(self):
return self.title
I have this 2 models
from django.db import models
def get_upload_path(instance, filename):
return '{0}/{1}'.format(instance.imovel.id, filename)
# Create your models here.
class Imovel(models.Model):
nome = models.CharField(max_length=50)
descricao = models.CharField(max_length=800)
area = models.IntegerField()
quartos = models.SmallIntegerField(null=True, blank=True)
banheiros = models.SmallIntegerField()
disponivel_aluguel = models.BooleanField()
disponivel_venda = models.BooleanField()
valor_aluguel = models.DecimalField(max_digits=15, decimal_places=2)
valor_venda = models.DecimalField(max_digits=15, decimal_places=2)
valor_condominio = models.DecimalField(max_digits=15, decimal_places=2)
valor_iptu = models.DecimalField(max_digits=15, decimal_places=2)
capa = models.OneToOneField('ImagemImovel', related_name='capa', on_delete=models.DO_NOTHING, null=True, blank=True)
def __str__(self):
return self.nome
class Meta:
db_table = 'imovel'
class ImagemImovel(models.Model):
imovel = models.ForeignKey(Imovel, related_name='imagens', on_delete=models.CASCADE)
nomeImagem = models.CharField(max_length=20)
imagem = models.ImageField(upload_to=get_upload_path)
def __str__(self):
return self.nomeImagem
class Meta:
db_table = 'imagemImovel'
I have houses and it's pictures and a field named 'capa' to say which one is the main picture.
The problem is when I add a house through django admin, save and come back to choose the main one it let me choose images from other houses. How could I filter it to just show images that are related to this specific house?
My django admin file
from django.contrib import admin
from .models import ImagemImovel, Imovel
# Register your models here.
class ImagemImovelAdmin(admin.TabularInline):
model = ImagemImovel
class ImovelAdmin(admin.ModelAdmin):
inlines = (ImagemImovelAdmin, )
admin.site.register(Imovel, ImovelAdmin)
I changed my ImovelAdmin class so I can get the id from the model using the get_form function and use it in a filter for the queryset
class ImovelAdmin(admin.ModelAdmin):
inlines = (ImagemImovelAdmin, )
id_for_formfield = None
def get_form(self, request, obj=None, **kwargs):
if obj:
self.id_for_formfield = obj.id
return super(ImovelAdmin, self).get_form(request, obj, **kwargs)
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == "capa" and self.id_for_formfield is not None:
kwargs["queryset"] = ImagemImovel.objects.filter(imovel=self.id_for_formfield)
return super(ImovelAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
admin.site.register(Imovel, ImovelAdmin)
I have two functions projectTimerStart to start the timer and projectTimerStop
i want to use the object which is created in projectTimerStart and i want to end the time when projectTimerStop , and this should be saved in a database
ps: Both the functions are not in class they are normal functions
def projectTimerStart(request, slug):
project_detail = Project.objects.get(slug=slug)
b = ProjectTimer(time_started=datetime.now(),
working_project=project_detail,
working_freelancer=request.user
)
b.save()
return HttpResponseRedirect(reverse('project_timer', kwargs=
{"slug":slug}))
def projectTimerStop(request, slug):
project_detail = Project.objects.get(slug=slug)
#i want something here super method or something
return HttpResponseRedirect(reverse('project_timer', kwargs=
{"slug": slug}))
models.py
class Project(models.Model):
project_title = models.CharField(max_length=100)
project_description = models.TextField()
created_by = models.ForeignKey(
User, on_delete=models.CASCADE, related_name='created')
assigned_to = models.ManyToManyField(
User, blank=True, related_name='assigned_by')
slug = models.SlugField()
hourly_budget = models.PositiveIntegerField(blank=True, null=True)
technologies = models.ManyToManyField(
Technologies, related_name='technologies_used')
time_posted = models.DateTimeField(auto_now_add=True)
request_id = models.ManyToManyField(
User, related_name='requested_by', blank=True)
def __str__(self):
return self.project_title
def save(self, *args, **kwargs):
self.slug = slugify(self.project_title)
super(Project, self).save(*args, **kwargs)
def get_absolute_url(self):
return reverse('project_detail', kwargs={'slug': self.slug})
def get_timer_url(self):
return reverse('project_timer', kwargs={'slug': self.slug})
def round_datetime(dt):
minutes = round((dt.minute + float(dt.second) / 60) / 15) * 15 -
dt.minute
return dt + datetime.timedelta(minutes=minutes, seconds=-dt.second)
class ProjectTimer(models.Model):
time_started = models.DateTimeField()
time_ended = models.DateTimeField(blank=True, null=True)
working_project = models.ForeignKey(Project, on_delete=models.CASCADE)
working_freelancer = models.ForeignKey(
User, on_delete=models.CASCADE, blank=True, null=True)
If each of your project objects will have one and only project timer objects, you can add project_timer = models.OneToOneField(ProjectTimer) to your Project model and access to the project timer by using project_detail.project_timer.
If not, you need to know at least one feature of that project_timer in order to fetch it from database. Or you can iterate all of your ProjectTimer objects that belongs to that Project and select the appropriate one by:
models.py
class Project(models.Model):
# Some fields
project_timers = models.ManyToManyField(ProjectTimer)
views.py
def projectTimerStop(request, slug):
project_detail = Project.objects.get(slug=slug)
for pt in project_detail.project_timers.all():
if pt.some_field == "THIS IS CORRECT TIMER":
# Here is your project_detail
print(str(pt))
return HttpResponseRedirect(reverse('project_timer', kwargs=
{"slug": slug}))
I have created 'post' model in which I included 'post_id' as the primary key field. When I am trying to create a post, it is raising an error: 'badly formed hexadecimal UUID string'. I would appreciate helping me in solve this.
Here's my code.
Models.py:
class Post(models.Model):
post_id = models.UUIDField(primary_key=True, default='uuid.uuid4', editable=False)
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1)
from1 = models.CharField(max_length=20)
To = models.CharField(max_length=20)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
objects = PostManager()
def __unicode__(self):
return self.post_id
def __str__(self):
return self.post_id
def get_absolute_url(self):
return reverse("posts:detail", kwargs={"post_id": self.post_id})
class Meta:
ordering = ["-timestamp", "-Time"]
views.py:
def post_create(request):
form = PostForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
print(form.cleaned_data.get("post_id"))
instance.user = request.user
instance.save()
return HttpResponseRedirect(instance.get_absolute_url())
context = {
"form": form,
}
return render(request, "loggedin_load/post_load.html", context)
I would do something like this:
from django.utils.encoding import python_2_unicode_compatible
#python_2_unicode_compatible
class Post(models.Model):
# Instead of default, maybe do null=True to take old entries into account?
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1)
from1 = models.CharField(max_length=20)
# You may want to reconsider the naming of the "To" field
# to avoid capital letters and built-in functions
To = models.CharField(max_length=20)
timestamp = models.DateTimeField(auto_now_add=True)
objects = PostManager()
# You can remove this with the decorator above
# def __unicode__(self):
# return self.id
def __str__(self):
return self.id # acts as your post_id
def get_absolute_url(self):
return reverse("posts:detail", kwargs={"post_id": self.id})
class Meta:
ordering = ["-timestamp", "-Time"]
Whenever an object is created, it will automatically be assigned an id, which will populate your __unicode__, __str__, and get_absolute_url.
You need to import the module and not use quotes around 'uuid.uuid4'.
It should be somewhat like:
import uuid # The uuid module
class Post(models.Model):
post_id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) # using the function uuid4 on the module
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1)
from1 = models.CharField(max_length=20)
To = models.CharField(max_length=20)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
objects = PostManager()
def __unicode__(self):
return self.post_id
def __str__(self):
return self.post_id
def get_absolute_url(self):
return reverse("posts:detail", kwargs={"post_id": self.post_id})
class Meta:
ordering = ["-timestamp", "-Time"]
N.B I've not tested the above code, and I agree with some of the comments you shouldn't need a UUID for the post_id. Without knowing more I couldn't help further.