I'm trying to do a very basic test:
public function testUsernameIsRequired(){
$user = new User;
$user->email = "phil#ipbrown.com";
// User should not save
$this->assertFalse($user->save());
}
on the following model:
class User extends Eloquent implements UserInterface, RemindableInterface {
use SoftDeletingTrait;
protected $fillable = array('email', 'username', 'password');
public static $rules = array(
'email' => 'required|min:3',
'username' => 'required|min:3',
'password' => 'required|min:3'
);
}
According to my thinking (...yeah) this test should succeed, as a User model which gets saved without required fields doesn't actually save.
But this Model somehow does save, doesn't throw any errors and creates a completely empty User.
Any ideas as to what I'm doing wrong?
$rules is just something you made up - it wont work out of the box like that. You need to actually validate the models against the rules to enforce it on save.
Laravel 4 - Trouble overriding model's save method will do what you want without Ardent.
Related
I'm having problems making queries and creating / updating / deleting things in django graphql through the graphql plugin of vuex orm.
From the interface provided by django to execute queries, I can perfectly use my mutations and consult any particular data or any collection of them.
I'm going to write an example of how I create an object called "TipoProducto" from the django interface:
mutation myMutation {
createTipoProducto(input: {nombre:"Pizza", descripcion:"foobar"}) {
tipoProducto {nombre, descripcion}
status
}
}
This code will return the object with its attributes and a status 200 if it was successful.
The Django classes in the schema:
class TipoProductoNode(DjangoObjectType):
class Meta:
model = TipoProducto
filter_fields = ['nombre', 'productos']
interfaces = (relay.Node, )
class TipoProducto(graphene.ObjectType):
nombre = graphene.String()
descripcion = graphene.String()
class CreateTipoProducto(graphene.ClientIDMutation):
class Input:
nombre = graphene.String(required=True)
descripcion = graphene.String(required=True)
tipo_producto = graphene.Field(TipoProducto)
status = graphene.Int()
ok = graphene.Boolean()
def mutate_and_get_payload(self, info, nombre, descripcion, client_id_mutation=None):
tipo_producto = TipoProductoNode._meta.model(nombre=nombre, descripcion=descripcion)
tipo_producto.save()
return CreateTipoProducto(tipo_producto=tipo_producto, ok=bool(tipo_producto.id), status=200)
My model in vuex orm:
import { Model } from '#vuex-orm/core';
import Product from './Product'
export default class TipProd extends Model {
static entity = "tipProds"
static fields () {
return {
id: this.increment(),
nombre: this.attr(''),
descripcion: this.attr(''),
producto: this.hasMany(Product, 'tipProd_id')
}
}
}
This is the method I try to use to create a new object "TipoProducto":
methods: {
async register (tipProduct) {
await TipProd.insert({
data:
tipProduct
});
const tipProd = TipProd.query().last()
await tipProd.$mutate({ name: 'createTipoProducto' });
}
where data: tipProducto are the attributes taken from a form
I can not find the way that vuex orm correctly structured the query to create an object. What am I doing wrong?
I did not get apollo devtools to work in order to debug the exit of the vuex-orm. I have no idea how the query is being created.
Sorry for the english and thanks.
The structure was fine, I could not see the query because there was none, I failed the connection between Django Graphene and Vuex-ORM Graphql plugin, since the API side had badly defined mutations.
I have a user model with one of the columns is 'apikey'. I just want that 'apikey' can be accessed only by its user.
Should I use a different model such as 'Account' which columns are 'apikey' and its id, and make ACL to that model?
Or, should I tweak the remote method?
Any suggestions on how to do that?
I would delete the property apikey before giving the response to the client, based on user permissions.
This is a code example, you should adapt it to your needs.
User.afterRemote('findById', (context, user, next) => {
let userId = context.req.accessToken.userId
if (!userId || user.id !== userId) {
context.result.apykey = undefined
}
next()
})
getting problem with authentication in laravel as I have username and password in different tables.As Auth uses same table for username and password but my database is already setup where the the username is in table users and the password is in table webpages_membership, and I cant change the database structure because that database is used by other mobile application and website too. So how do I use Auth for login system.
#btl:
I tried the solution but now there is another error of
"Undefined index: password" in vendor\laravel\framework\src\Illuminate\Auth\GenericUser.php
following is my user model code.
Code:
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use App\WebPages_Membership;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $table = 'Users';
protected $dbPrefixOveride = '';
protected $primaryKey = 'UserId';
protected $fillable = [
'Username', 'FirstName', 'LastName','Email','MobileNumber','CreatedBy','CreatedDate','ModifiedBy','ModifiedDate','DistributorId','Telephone','IsAuthorized','AlternateMobileNumber','AlternateEmail','IsDeleted','UnauthorizationRemark'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
/*protected $hidden = [
'password', 'remember_token',
];*/
public function webpagesMembership() {
return $this->hasOne(WebPages_Membership::class);
}
public function getPasswordAttribute() {
return $this->webpagesMembership->getAttribute('Password');
}
}
?>
I'd do something like this. Assuming a one-to-one relationship between your tables.
Define a relationship between User and WebpagesMembership models. Your User model would have the following:
public function webpagesMembership() {
return $this->hasOne(WebpagesMembership::class);
}
Add an accessor function
public function getPasswordAttribute() {
return $this->webpagesMembership->getAttribute('password');
}
That way Auth will work when it attempts to access the password attribute on your User model.
Edit:
Add password to the User model's $appends property:
protected $appends = [
'password'
];
This will act as if it were an attribute on the model now. The error you encountered was because the GenericUser's attributes were being set in the constructor and password did not exist. It then attempted to access password in:
public function getAuthPassword()
{
return $this->attributes['password'];
}
Hence, the undefined index.
I am a bit frustrated with this problem using the Django Rest Framework:
I am using a viewset, with a custom serializer. This serializer has its depth set to 1. When i query this viewset I get the correct representation of data for example:
data = {
id: 1,
issue_name: 'This is a problem',
status: {
id: 3,
name: 'todo'
}
}
The problem comes in when I need to update the status. For example if I want to select another status for this issue, for example:
status_new = {
id: 4,
name: 'done'
}
I send the following PATCH back to the server, this is the output:
data = {
id: 1,
issue_name: 'This is a problem',
status: {
id: 4,
name: 'done'
}
}
However, the status does not get updated. Infact, it is not even a part of the validated_data dictionary. I have read that nested relations are read-only. Could someone please tell me what I need to do this in a simple way?
Would really be obliged.
Thanks in advance
As stated in the documentation, you will need to write your own create() and update() methods in your serializer to support writable nested data.
You will also need to explicitly add the status field instead of using the depth argument otherwise I believe it won't be automatically added to validated_data.
EDIT: Maybe I was a bit short on the details: what you want to do is override update in ModelIssueSerializer. This will basically intercept the PATCH/PUT requests on the serializer level. Then get the new status and assign it to the instance like this:
class StatusSerializer(serializers.ModelSerializer):
class Meta:
model = Status
class ModelIssueSerializer(serializers.ModelSerializer):
status = StatusSerializer()
# ...
def update(self, instance, validated_data):
status = validated_data.pop('status')
instance.status_id = status.id
# ... plus any other fields you may want to update
return instance
The reason I mentioned in the comment that you might need to add a StatusSerializer field is for getting status into validated_data. If I remember correctly, if you only use depth then nested objects might not get serialized inside the update() / create() methods (although I might be mistaken on that). In any case, adding the StatusSerializer field is just the explicit form of using depth=1
I usually use custom field for such cases.
class StatusField(serializers.Field):
def to_representation(self, value):
return StatusSerializer(value).data
def to_internal_value(self, data):
try:
return Status.objects.filter(id=data['id']).first()
except (AttributeError, KeyError):
pass
And then in main serializer:
class IssueSerializer(serializers.ModelSerializer):
status = StatusField()
class Meta:
model = MyIssueModel
fields = (
'issue_name',
'status',
)
I would assume that your models mimic your serializer's data. Also, I would assume that you have a one to many relation with the status(es) but you don't need to create them via the issue serializer, you have a different endpoint for that. In such a case, you might get away with a SlugRelatedField.
from rest_framework import serializers
class StatusSerializer(serializers.ModelSerializer):
class Meta:
model = MyStatusModel
fields = (
'id',
'status',
)
class IssueSerializer(serializers.ModelSerializer):
status = serializers.SlugRelatedField(slug_field='status', queryset=MyStatusModel.objects.all())
class Meta:
model = MyIssueModel
fields = (
'issue_name',
'status',
)
Another valid solution would be to leave here the foreign key value and deal with the display name on the front-end, via a ui-select or select2 component - the RESTfull approach: you are handling Issue objects which have references to Status objects. In an Angular front-end app, you would query all the statuses from the back-end on a specific route and then you will display the proper descriptive name based on the foreign key value form Issue.
Let me know how is this working out for you.
What is the best way to display information from related objects on my Backbone.js wired front-end when on the backend these attributes are stored on separate Django models in a PostgreSQL database?
I am currently using Django, Tastypie, Django-Tastypie, Backbone.js, Backbone-Relational and Handlebars.js templates. I am open to doing things differently and I am willing to learn new technologies such as Riak if it's necessary or more efficient.
On the front-end what I'm trying to do would be very simple with standard Django templates: display a list of tags on a post and the author of that post.
On the back-end I have a Post model and Tag, User and UserProfile (author) models. Users and UserProfiles are 1-to-1, Post has a relation to UserProfile but what I want to display is stored on the User model under the attribute username. At the moment this involves two painstaking lookups to get the author's username for every post. The Post model:
class Post(models.Model):
author = models.ForeignKey(UserProfile)
topic = models.ForeignKey(Topic)
tags = models.ManyToManyField(Tag)
content = models.TextField()
title = models.CharField(max_length=250)
slug = models.SlugField()
description = models.TextField()
In Coffeescript I have my Backbone models. At present I am trying to fetch the relevant author and tag objects when a Post model is initialized. My current code is very sloppy and I apologize, my javascript foo is still under development!
class User extends Backbone.RelationalModel
class UserProfile extends Backbone.RelationalModel
urlRoot : '/api/v1/profile/?format=json'
class PostTag extends Backbone.RelationalModel
initialize: ->
this.get('tag').on 'change', ( model ) =>
this.get( 'post' ).trigger( 'change:tag', model )
class Tag extends Backbone.RelationalModel
urlRoot: '/api/v1/tag/?format=json'
idAttribute: 'id',
relations: [{
type: Backbone.HasMany,
key: 'post_tags',
relatedModel: PostTag,
reverseRelation: {
key: 'tag',
includeInJSON: 'id',
},
}],
class Post extends Backbone.RelationalModel
idAttribute: 'id',
relations: [{
type: Backbone.HasMany,
key: 'post_tags',
relatedModel: PostTag,
reverseRelation: {
key: 'post',
includeInJSON: 'id',
},
}]
initialize: ->
#.get('tags').forEach(#addTag, #)
#.addAuthor()
#.on 'change:tag', (model) ->
console.log('related tag=%o updated', model)
addAuthor: () ->
profile_id = #.get('author')
if app.UserProfiles.get(profile_id)?
profile = app.UserProfiles.get(profile_id)
user = app.Users.get(profile.user)
#.set('author_name',user.get('username'))
else
profile = new app.UserProfile(profile_id)
app.UserProfiles.add(profile)
profile.fetch(success: (model,response) =>
user_id = profile.get('user')
if app.Users.get(user_id)?
user = app.Users.get(user_id)
user.fetch(success: (model,response) =>
console.log(user.get('username'))
#.set('author_name',user.get('username'))
)
console.log("Existing user"+user_id)
console.log(user.get('username'))
##.set('author_name',user.get('username'))
else
user = new app.User('resource_uri':user_id)
app.Users.add(user)
console.log("New user"+user_id)
user.fetch(success: (model,response) =>
console.log(user.get('username'))
#.set('author_name',user.get('username'))
)
)
addTag: (tag_id) ->
console.log(tag_id)
if app.Tags.get(tag_id)?
tag = app.Tags.get(tag_id)
console.log("TAG" + tag)
else
console.log("NON EXISTENT")
console.log(tag_id)
tag = new app.Tag({'id':tag_id})
tag.fetch()
app.Tags.add(tag)
post_tag = new app.postTag({
'tag': tag_id,
'post': #.get('resource_uri')
})
#.get('post_tags').add(post_tag)
This code actually works fine for fetching and storing the related objects but it's incredibly messy and I'm sure there must be a better way. Further, I can't figure out a way to access the stored tag names to display in my Handlebars.js templates.
When writing this I found the related question How do I load sub-models with a foreign key relationship in Backbone.js?
Since I'd already written the question I figured I may as well post it in case it's useful for anyone.
The answer was as simple as adding full=True to my tastypie resources. I could then get rid of the addTags and addAuthor functions and since I don't need to save or update the related objects the rest of the answer in the above thread wasn't necessary for me.