How to create in secondary database using Django - django

dbrouter.py
class DbRouter(object):
mhris = [HrUserMstr]
profocus_db = [VendorEntry, ApVendorMt, ApVendorDt, ApVendorCertificateDt]
apps_ppl = []
def db_for_read(self, model, **hints):
if model in self.profocus_db:
return 'PROFOCUS_DB'
elif model in self.apps_ppl:
return 'APPS_PPPL'
elif model in self.mhris:
return 'MHRIS'
else:
return 'default'
def db_for_write(self, model, **hints):
if model in self.profocus_db:
return 'PROFOCUS_DB'
elif model in self.apps_ppl:
return 'APPS_PPPL'
elif model in self.mhris:
return 'MHRIS'
else:
return 'default'
def allow_migrate(self, db, app_label, model_name=None, **hints):
if model_name in self.profocus_db:
return 'PROFOCUS_DB'
elif model_name in self.apps_ppl:
return 'APPS_PPPL'
elif model_name in self.mhris:
return 'MHRIS'
else:
return 'default'
models.py
class ApVendorDt(models.Model):
certificate = models.ForeignKey(ApVendorCertificateDt, on_delete=models.CASCADE)
vendor_code = models.CharField(max_length=30, default='')
vendor_doc = models.FileField(upload_to='vendor_doc/')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.vendor_id
class Meta:
db_table = 'APVENDOR_DT'
db_for_write and db_for_read functions are working fine but allow_migrate is not working. I'm trying to create a new table using django model it is creating table in default database But I want to create table in only profocus_db which is my secondary database.
django 4.0.1

Related

how to pass the Integrity error django and DRF without stoping execution raising the error

I am byulding an API using django and DRF my code is this
models.py
class Company(models.Model):
"""Company object."""
name_company = models.CharField(max_length=255)
symbol = models.CharField(max_length=10, unique=True)
cik = models.CharField(max_length=150, blank=True)
sector = models.CharField(max_length=150, blank=True)
industry_category = models.CharField(max_length=150, blank=True)
company_url = models.TextField(blank=True)
description = models.TextField(blank=True)
def __str__(self):
return self.name_company
views.py
class CompanyViewSet(viewsets.ModelViewSet):
"""View for manage company APIs."""
serializer_class = serializers.CompanyDetailSerializer
queryset = Company.objects.all()
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated]
def get_serializer_class(self):
"""Return the serializer class for request."""
if self.action == 'list':
return serializers.CompanySerializer
return self.serializer_class
def perform_create(self, serializer):
"""Create a new Company."""
try:
serializer.save()
except IntegrityError:
print('Symbol exists already.')
pass
serializers.py
class CompanySerializer(serializers.ModelSerializer):
"""Serializer for Company."""
class Meta:
model = Company
fields = [
'id', 'name_company', 'symbol', 'cik', 'sector',
'industry_category', 'company_url',
]
read_only_fields = ['id']
def create(self, validated_data):
try:
instance, created = Company.objects.get_or_create(**validated_data)
if created:
return instance
except IntegrityError:
pass
class CompanyDetailSerializer(CompanySerializer):
"""Serializer for Company details."""
class Meta(CompanySerializer.Meta):
fields = CompanySerializer.Meta.fields + ['description']
And right now i am doing unit tests using in this file.
test_company.py
def create_company(**params):
"""Create and return a sample company."""
defaults = {
'name_company': 'Apple',
'symbol': 'AAPL',
'cik': '0000320193',
'sector': 'Technology',
'industry_category': 'Consumer Electronics',
'company_url': 'https://www.apple.com/',
'description':'',
}
defaults.update(params)
company = Company.objects.create(**defaults)
return company
def test_retrieve_companies(self):
"""Test retrieving a list of Companies."""
create_company()
create_company()
create_company(
name_company='Tesla',
symbol='TSLA',
)
res = self.client.get(COMPANIES_URL)
companies = Company.objects.all().order_by('id')
serializer = CompanySerializer(companies, many=True)
self.assertEqual(res.status_code, status.HTTP_200_OK)
self.assertEqual(res.data, serializer.data)
I am getting IntegrityError, what i want is that the run time continue without stopping execution raising the error that is why i am testing it inserting APPLE twice.
I am trying to catch the error with this code in the views.py but does not catch it.
def perform_create(self, serializer):
"""Create a new Company."""
try:
serializer.save()
except IntegrityError:
print('Symbol exists already.')
pass
my error is this:
django.db.utils.IntegrityError: duplicate key value violates unique constraint "core_company_symbol_50a489f1_uniq"
DETAIL: Key (symbol)=(AAPL) already exists.
Thank you in advance.

DJANGO - Models.Forms - Usuarios

I'm trying to save and retrive the data owned by the user.
I mean, in one Sqlite3 DB I store the tables for all users but each one has their one data store in it, how can I give each one their own data.
this are my models, view and form
MODEL.PY
class Cuentas (models.Model):
rubro_cta = models.ForeignKey(TipoC, on_delete=models.CASCADE, verbose_name = u'Tipo')
sub_rubro_cta = models.ForeignKey(Sub_rubro, on_delete=models.CASCADE, verbose_name = u'Sub Rubro')
titulo_cuenta = models.CharField(max_length=50)
detalle_cuenta = models.CharField(max_length=60)
importe_cuenta = models.FloatField()
def save(self, *args, **kwargs):
self.importe_cuenta = round(self.importe_cuenta, 2)
super(Cuentas, self).save(*args, **kwargs)
def __str__(self):
return self.detalle_cuenta
FORMS.PY
class CuentasForm (forms.ModelForm):
class Meta:
model = Cuentas
fields = ['rubro_cta', 'sub_rubro_cta', 'detalle_cuenta', 'importe_cuenta']
labels = {
'rubro_cta': _('Cuenta'),
'sub_rubro_cta': _('Tipo'),
'detalle_cuenta': _('Detalle'),
'importe_cuenta': _('Importe'),
}
VIEWS.PY
#login_required
def carga (request):
if request.method == 'POST':
form = CuentasForm(request.POST)
if form.is_valid:
form.save()
return redirect('balance')
else:
form = CuentasForm()
return render (request, "ProyetoWebApp/carga.html",{"form": form})
you have to add a foreign key field to user in your Cuentas class:
class Cuentas (models.Model):
user = models.ForeignKey(User, models.CASCADE)
...
in your view add this code for GET method:
info = None
if request.method == 'GET':
info = Cuentas.objects.get(user=request.user)
return render (request, "ProyetoWebApp/carga.html",{"form": form, "info":info})

Django - using model manager method in Admin filter

I'm using Django 2.0
I have a model class with custom Manager in models.py
class MockTestQuerySet(models.query.QuerySet):
def upcoming(self):
return self.filter(start_date__gte=datetime.now())
def past(self):
return self.filter(end_date__lte=datetime.now())
class MockTestManager(models.Manager):
def get_queryset(self):
return MockTestQuerySet(self.model, self._db)
def upcoming_tests(self):
return self.get_queryset().upcoming()
def past_tests(self):
return self.get_queryset().past()
def is_past(self, mock_pk):
mock_test = self.get_queryset().past().filter(pk=mock_pk).first()
if mock_test is not None:
return True
return False
def is_future(self, mock_pk):
mock_test = self.get_queryset().upcoming().filter(pk=mock_pk).first()
if mock_test is not None:
return True
return False
class MockTest(models.Model):
title = models.CharField(max_length=250, null=False, blank=False)
start_date = models.DateTimeField()
end_date = models.DateTimeField()
modified = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)
objects = MockTestManager()
class Meta:
db_table = 'mock_tests'
ordering = ['start_date']
Now, I'm working on Admin module and want to create filter which filters upcoming or past tests by calling past_tests() or upcoming_tests()
Till now, I have tried this in admin.py
class InPast(admin.SimpleListFilter):
def lookups(self, request, model_admin):
pass
title = _('Past Mock Tests')
parameter_name = 'past'
def queryset(self, request, queryset):
return queryset.past_tests()
#admin.register(MockTest)
class MockTestAdmin(admin.ModelAdmin):
list_display = ['title', 'start_date', 'end_date', 'duration']
list_filter = [
InPast
]
I know, I'm doing it wrong but could not figure out how to do it.

Update if exists or create Model in Django Rest

I got this model:
class Like(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey(settings.AUTH_USER_MODEL)
post = models.ForeignKey('posts.Post', blank=True, null=True)
RATING_CONVERSION = (
(1, '+'),
(0, '0'),
(-1, '-'),
)
userRating = models.SmallIntegerField(choices=RATING_CONVERSION)
def __int__(self):
return self.id
If post id and user id exists I need to update rating.
I try to make it.
Serializer:
class LikeSerializer(serializers.ModelSerializer):
user = serializers.PrimaryKeyRelatedField(queryset=ExtUser.objects.all(), required=False, allow_null=True,default=None)
class Meta:
model = Like
field = ('user', 'post')
validators = [
UniqueTogetherValidator(
queryset=Like.objects.all(),
fields=('user', 'post')
)
]
def validate_user(self, value):
return self.context['request'].user
def create(self, validated_data):
return Like.objects.create(**validated_data)
And ViewSet
class LikeViewSet(viewsets.ModelViewSet):
queryset = Like.objects.all()
serializer_class = LikeSerializer
#detail_route(methods=['post', 'get'])
def get_object(self):
if self.request.method == 'POST':
like = Like.objects.get(user=self.context['request'].user, post = self.context['request'].post)
if like:
return like
else:
return Like(id=self.kwargs.get('pk'))
else:
return super(LikeViewSet, self).get_object()
I found a lot of information how to create or update using pk in Url, but I got parameters inside of JSON
This method doesn't work - instead of update rating it creates new Model objects

Django reverse foreignkey relationship failing

I have set up two models where one has a foreign key relationship to the other. Since I have multiple databases I also set up a routers.py file as both databases live in the same application. I have been reading and following the documenation found here and here and as far as I can tell I am following the documentation to the letter.
models.py
class Customers(models.Model):
customer_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100)
active = models.IntegerField()
class Meta:
db_table = 'customers'
app_label = 'db1'
class Users(models.Model):
user_id = models.AutoField(primary_key=True)
customer = models.ForeignKey(Customers, models.CASCADE)
username = models.CharField(max_length=35)
role = models.ForeignKey(Roles, models.CASCADE)
active = models.IntegerField()
class Meta:
db_table = 'users'
app_label = 'db1'
routers.py
class BackendRouter(object):
def db_for_read(self, model, **hints):
if model._meta.app_label == 'db1':
return 'default'
elif model._meta.app_label == 'db2':
return 'db2'
return None
def db_for_write(self, model, **hints):
if model._meta.app_label == 'db1':
return 'default'
elif model._meta.app_label == 'db2':
return 'db2'
return None
def allow_relation(self, obj1, obj2, **hints):
if obj1._meta.app_label == 'db1' or \
obj2._meta.app_label == 'db1':
return True
elif obj1._meta.app_label == 'db2' or \
obj2._meta.app_label == 'db2':
return True
return None
def allow_migrate(self, db, app_label, model_name=None, **hints):
if app_label == 'db1':
return db == 'default'
elif app_label == 'db2':
return db == 'db2'
return None
Ignore for a second that I have a users table without deriving from AbstractBaseUser, when I run the following query:
Customers.objects.filter(users__username__contains='sl')
I get the following error:
django.core.exceptions.FieldError: Cannot resolve keyword 'users' into
field. Choices are: active, customer_id, name
Per the example in the documentation:
Blog.objects.filter(entry__headline__contains='Lennon')
This should work. What am I missing here?
As a point of reference I have already tried the following as well:
Customers.objects.filter(users_set__username__contains=‘sl’)
As well as setting related_name='users' on the customers ForeignKey.
Based on the docs, it seems I should be able to filter the way I have in my question and not run into an issue. However I am not sure if I can actually filter on more than a single object when doing "reverse" relations. I did achieve what I wanted with the following solution:
user = Users.objects.filter(username='someuser').only('customer_id')
customer = Customers.objects.filter(customer_id__in=user)
I am sure there is a more efficient way though. Like such:
Users.objects.filter(username='someuser').values_list('customer__name', flat=True)[0]
I just figured it would be better if I could get what I need via something like:
Customers.objects.filter(users__username='someuser').values_list('name', flat=True)[0]
It actually appears that this was caused by both of my models living in the same application. Once I split them out into there own seperate apps, reverse relationships began to work.